digitaltwin-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +125 -0
- package/dist/components/assets_manager.d.ts +384 -0
- package/dist/components/assets_manager.d.ts.map +1 -0
- package/dist/components/assets_manager.js +637 -0
- package/dist/components/assets_manager.js.map +1 -0
- package/dist/components/collector.d.ts +62 -0
- package/dist/components/collector.d.ts.map +1 -0
- package/dist/components/collector.js +80 -0
- package/dist/components/collector.js.map +1 -0
- package/dist/components/global_assets_handler.d.ts +63 -0
- package/dist/components/global_assets_handler.d.ts.map +1 -0
- package/dist/components/global_assets_handler.js +127 -0
- package/dist/components/global_assets_handler.js.map +1 -0
- package/dist/components/handler.d.ts +33 -0
- package/dist/components/handler.d.ts.map +1 -0
- package/dist/components/handler.js +27 -0
- package/dist/components/handler.js.map +1 -0
- package/dist/components/harvester.d.ts +54 -0
- package/dist/components/harvester.d.ts.map +1 -0
- package/dist/components/harvester.js +253 -0
- package/dist/components/harvester.js.map +1 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +6 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/interfaces.d.ts +18 -0
- package/dist/components/interfaces.d.ts.map +1 -0
- package/dist/components/interfaces.js +2 -0
- package/dist/components/interfaces.js.map +1 -0
- package/dist/components/types.d.ts +47 -0
- package/dist/components/types.d.ts.map +1 -0
- package/dist/components/types.js +2 -0
- package/dist/components/types.js.map +1 -0
- package/dist/database/adapters/knex_database_adapter.d.ts +47 -0
- package/dist/database/adapters/knex_database_adapter.d.ts.map +1 -0
- package/dist/database/adapters/knex_database_adapter.js +180 -0
- package/dist/database/adapters/knex_database_adapter.js.map +1 -0
- package/dist/database/database_adapter.d.ts +92 -0
- package/dist/database/database_adapter.d.ts.map +1 -0
- package/dist/database/database_adapter.js +6 -0
- package/dist/database/database_adapter.js.map +1 -0
- package/dist/engine/digital_twin_engine.d.ts +237 -0
- package/dist/engine/digital_twin_engine.d.ts.map +1 -0
- package/dist/engine/digital_twin_engine.js +574 -0
- package/dist/engine/digital_twin_engine.js.map +1 -0
- package/dist/engine/endpoints.d.ts +7 -0
- package/dist/engine/endpoints.d.ts.map +1 -0
- package/dist/engine/endpoints.js +18 -0
- package/dist/engine/endpoints.js.map +1 -0
- package/dist/engine/events.d.ts +13 -0
- package/dist/engine/events.d.ts.map +1 -0
- package/dist/engine/events.js +11 -0
- package/dist/engine/events.js.map +1 -0
- package/dist/engine/initializer.d.ts +8 -0
- package/dist/engine/initializer.d.ts.map +1 -0
- package/dist/engine/initializer.js +23 -0
- package/dist/engine/initializer.js.map +1 -0
- package/dist/engine/queue_manager.d.ts +78 -0
- package/dist/engine/queue_manager.d.ts.map +1 -0
- package/dist/engine/queue_manager.js +167 -0
- package/dist/engine/queue_manager.js.map +1 -0
- package/dist/engine/scheduler.d.ts +30 -0
- package/dist/engine/scheduler.d.ts.map +1 -0
- package/dist/engine/scheduler.js +378 -0
- package/dist/engine/scheduler.js.map +1 -0
- package/dist/env/env.d.ts +25 -0
- package/dist/env/env.d.ts.map +1 -0
- package/dist/env/env.js +55 -0
- package/dist/env/env.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/storage/adapters/local_storage_service.d.ts +29 -0
- package/dist/storage/adapters/local_storage_service.d.ts.map +1 -0
- package/dist/storage/adapters/local_storage_service.js +50 -0
- package/dist/storage/adapters/local_storage_service.js.map +1 -0
- package/dist/storage/adapters/ovh_storage_service.d.ts +32 -0
- package/dist/storage/adapters/ovh_storage_service.d.ts.map +1 -0
- package/dist/storage/adapters/ovh_storage_service.js +70 -0
- package/dist/storage/adapters/ovh_storage_service.js.map +1 -0
- package/dist/storage/storage_factory.d.ts +14 -0
- package/dist/storage/storage_factory.d.ts.map +1 -0
- package/dist/storage/storage_factory.js +36 -0
- package/dist/storage/storage_factory.js.map +1 -0
- package/dist/storage/storage_service.d.ts +26 -0
- package/dist/storage/storage_service.d.ts.map +1 -0
- package/dist/storage/storage_service.js +7 -0
- package/dist/storage/storage_service.js.map +1 -0
- package/dist/types/data_record.d.ts +17 -0
- package/dist/types/data_record.d.ts.map +1 -0
- package/dist/types/data_record.js +2 -0
- package/dist/types/data_record.js.map +1 -0
- package/dist/utils/logger.d.ts +17 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +35 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/map_to_data_record.d.ts +10 -0
- package/dist/utils/map_to_data_record.d.ts.map +1 -0
- package/dist/utils/map_to_data_record.js +21 -0
- package/dist/utils/map_to_data_record.js.map +1 -0
- package/dist/utils/servable_endpoint.d.ts +6 -0
- package/dist/utils/servable_endpoint.d.ts.map +1 -0
- package/dist/utils/servable_endpoint.js +15 -0
- package/dist/utils/servable_endpoint.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for Assets Manager components.
|
|
3
|
+
*
|
|
4
|
+
* Provides file upload, storage, and retrieval capabilities following the Digital Twin framework patterns.
|
|
5
|
+
* Each concrete implementation manages a specific type of asset and creates its own database table.
|
|
6
|
+
*
|
|
7
|
+
* @abstract
|
|
8
|
+
* @class AssetsManager
|
|
9
|
+
* @implements {Component}
|
|
10
|
+
* @implements {Servable}
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Create concrete implementations for different asset types
|
|
15
|
+
* class GLTFAssetsManager extends AssetsManager {
|
|
16
|
+
* getConfiguration() {
|
|
17
|
+
* return { name: 'gltf', description: 'GLTF 3D models manager', ... }
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* class PointCloudAssetsManager extends AssetsManager {
|
|
22
|
+
* getConfiguration() {
|
|
23
|
+
* return { name: 'pointcloud', description: 'Point cloud data manager', ... }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* // Usage in engine
|
|
28
|
+
* const gltfManager = new GLTFAssetsManager()
|
|
29
|
+
* gltfManager.setDependencies(database, storage)
|
|
30
|
+
*
|
|
31
|
+
* // Each creates its own table and endpoints:
|
|
32
|
+
* // - GLTFAssetsManager → table 'gltf', endpoints /gltf/*
|
|
33
|
+
* // - PointCloudAssetsManager → table 'pointcloud', endpoints /pointcloud/*
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* Asset metadata is stored as dedicated columns in the database table:
|
|
38
|
+
* - id, name, url, date (standard columns)
|
|
39
|
+
* - description, source, owner_id, filename (asset-specific columns)
|
|
40
|
+
*
|
|
41
|
+
* Each concrete AssetsManager creates its own table based on the configuration name.
|
|
42
|
+
*/
|
|
43
|
+
export class AssetsManager {
|
|
44
|
+
/**
|
|
45
|
+
* Injects dependencies into the assets manager.
|
|
46
|
+
*
|
|
47
|
+
* Called by the framework during component initialization.
|
|
48
|
+
*
|
|
49
|
+
* @param {DatabaseAdapter} db - The database adapter for metadata storage
|
|
50
|
+
* @param {StorageService} storage - The storage service for file persistence
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const assetsManager = new MyAssetsManager()
|
|
55
|
+
* assetsManager.setDependencies(databaseAdapter, storageService)
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
setDependencies(db, storage) {
|
|
59
|
+
this.db = db;
|
|
60
|
+
this.storage = storage;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validates that a source string is a valid URL.
|
|
64
|
+
*
|
|
65
|
+
* Used internally to ensure data provenance URLs are properly formatted.
|
|
66
|
+
*
|
|
67
|
+
* @private
|
|
68
|
+
* @param {string} source - The source URL to validate
|
|
69
|
+
* @returns {boolean} True if the source is a valid URL, false otherwise
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* this.validateSourceURL('https://example.com/data') // returns true
|
|
74
|
+
* this.validateSourceURL('not-a-url') // returns false
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
validateSourceURL(source) {
|
|
78
|
+
try {
|
|
79
|
+
new URL(source);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Upload a new asset file with metadata.
|
|
88
|
+
*
|
|
89
|
+
* Stores the file using the storage service and saves metadata to the database.
|
|
90
|
+
* Asset metadata is stored as dedicated columns in the database table.
|
|
91
|
+
*
|
|
92
|
+
* @param {CreateAssetRequest} request - The asset upload request
|
|
93
|
+
* @throws {Error} If source URL is invalid
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* await assetsManager.uploadAsset({
|
|
98
|
+
* description: '3D building model',
|
|
99
|
+
* source: 'https://city-data.example.com/buildings',
|
|
100
|
+
* owner_id: 'user123',
|
|
101
|
+
* filename: 'building.glb',
|
|
102
|
+
* file: fileBuffer
|
|
103
|
+
* })
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
async uploadAsset(request) {
|
|
107
|
+
if (!this.validateSourceURL(request.source)) {
|
|
108
|
+
throw new Error('Invalid source URL');
|
|
109
|
+
}
|
|
110
|
+
const config = this.getConfiguration();
|
|
111
|
+
const now = new Date();
|
|
112
|
+
// Store file using framework pattern
|
|
113
|
+
const url = await this.storage.save(request.file, config.name, request.filename);
|
|
114
|
+
// Create metadata with all asset-specific fields
|
|
115
|
+
const metadata = {
|
|
116
|
+
name: config.name,
|
|
117
|
+
type: config.contentType,
|
|
118
|
+
url,
|
|
119
|
+
date: now,
|
|
120
|
+
description: request.description,
|
|
121
|
+
source: request.source,
|
|
122
|
+
owner_id: request.owner_id,
|
|
123
|
+
filename: request.filename
|
|
124
|
+
};
|
|
125
|
+
await this.db.save(metadata);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Retrieve all assets for this component (like other components).
|
|
129
|
+
*
|
|
130
|
+
* Returns a JSON list of all assets with their metadata, following the
|
|
131
|
+
* framework pattern but adapted for assets management.
|
|
132
|
+
*
|
|
133
|
+
* @returns {Promise<DataResponse>} JSON response with all assets
|
|
134
|
+
*/
|
|
135
|
+
async retrieve() {
|
|
136
|
+
try {
|
|
137
|
+
const assets = await this.getAllAssets();
|
|
138
|
+
const config = this.getConfiguration();
|
|
139
|
+
// Transform to include asset metadata and user-friendly URLs
|
|
140
|
+
const assetsWithMetadata = assets
|
|
141
|
+
.map(asset => {
|
|
142
|
+
return {
|
|
143
|
+
id: asset.id,
|
|
144
|
+
name: asset.name,
|
|
145
|
+
date: asset.date,
|
|
146
|
+
contentType: asset.contentType,
|
|
147
|
+
// Asset-specific metadata (from DB columns)
|
|
148
|
+
description: asset.description || '',
|
|
149
|
+
source: asset.source || '',
|
|
150
|
+
owner_id: asset.owner_id || null,
|
|
151
|
+
filename: asset.filename || '',
|
|
152
|
+
// Add URLs that the front-end can actually use
|
|
153
|
+
url: `/${config.name}/${asset.id}`, // For display/use
|
|
154
|
+
download_url: `/${config.name}/${asset.id}/download` // For download
|
|
155
|
+
};
|
|
156
|
+
})
|
|
157
|
+
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); // Newest first
|
|
158
|
+
return {
|
|
159
|
+
status: 200,
|
|
160
|
+
content: JSON.stringify(assetsWithMetadata),
|
|
161
|
+
headers: { 'Content-Type': 'application/json' }
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
return {
|
|
166
|
+
status: 500,
|
|
167
|
+
content: JSON.stringify({
|
|
168
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
169
|
+
}),
|
|
170
|
+
headers: { 'Content-Type': 'application/json' }
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get all assets for this component type.
|
|
176
|
+
*
|
|
177
|
+
* Retrieves all assets managed by this component, with their metadata.
|
|
178
|
+
* Uses a very old start date to get all records.
|
|
179
|
+
*
|
|
180
|
+
* @returns {Promise<DataRecord[]>} Array of all asset records
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const allAssets = await assetsManager.getAllAssets()
|
|
185
|
+
* // Returns: [{ id, name, type, url, date, contentType }, ...]
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
async getAllAssets() {
|
|
189
|
+
const config = this.getConfiguration();
|
|
190
|
+
// Use getByDateRange with a very old start date to get all records
|
|
191
|
+
const veryOldDate = new Date('1970-01-01');
|
|
192
|
+
const farFutureDate = new Date('2099-12-31');
|
|
193
|
+
return await this.db.getByDateRange(config.name, veryOldDate, farFutureDate, 1000); // Max 1000 assets
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get asset by specific ID.
|
|
197
|
+
*
|
|
198
|
+
* @param {string} id - The asset ID to retrieve
|
|
199
|
+
* @returns {Promise<DataRecord | undefined>} The asset record or undefined if not found
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* const asset = await assetsManager.getAssetById('123')
|
|
204
|
+
* if (asset) {
|
|
205
|
+
* const fileData = await asset.data()
|
|
206
|
+
* }
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
async getAssetById(id) {
|
|
210
|
+
return await this.db.getById(id);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Update asset metadata by ID.
|
|
214
|
+
*
|
|
215
|
+
* Updates the metadata (description and/or source) of a specific asset.
|
|
216
|
+
* Asset metadata is stored as dedicated columns in the database.
|
|
217
|
+
*
|
|
218
|
+
* @param {string} id - The ID of the asset to update
|
|
219
|
+
* @param {UpdateAssetRequest} updates - The metadata updates to apply
|
|
220
|
+
* @throws {Error} If source URL is invalid or asset not found
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* await assetsManager.updateAssetMetadata('123', {
|
|
225
|
+
* description: 'Updated building model with new textures',
|
|
226
|
+
* source: 'https://updated-source.example.com'
|
|
227
|
+
* })
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
async updateAssetMetadata(id, updates) {
|
|
231
|
+
if (updates.source && !this.validateSourceURL(updates.source)) {
|
|
232
|
+
throw new Error('Invalid source URL');
|
|
233
|
+
}
|
|
234
|
+
const record = await this.db.getById(id);
|
|
235
|
+
if (!record) {
|
|
236
|
+
throw new Error(`Asset with ID ${id} not found`);
|
|
237
|
+
}
|
|
238
|
+
// Verify this asset belongs to our component
|
|
239
|
+
const config = this.getConfiguration();
|
|
240
|
+
if (record.name !== config.name) {
|
|
241
|
+
throw new Error(`Asset ${id} does not belong to component ${config.name}`);
|
|
242
|
+
}
|
|
243
|
+
// Apply updates, keeping existing values for non-updated fields
|
|
244
|
+
const updatedMetadata = {
|
|
245
|
+
id: parseInt(id),
|
|
246
|
+
name: config.name,
|
|
247
|
+
type: record.contentType,
|
|
248
|
+
url: record.url,
|
|
249
|
+
date: record.date, // Keep original date
|
|
250
|
+
description: updates.description ?? record.description ?? '',
|
|
251
|
+
source: updates.source ?? record.source ?? '',
|
|
252
|
+
owner_id: record.owner_id ?? null,
|
|
253
|
+
filename: record.filename ?? ''
|
|
254
|
+
};
|
|
255
|
+
// Update the record - delete and re-create with updated metadata
|
|
256
|
+
await this.db.delete(id);
|
|
257
|
+
await this.db.save(updatedMetadata);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Delete asset by ID.
|
|
261
|
+
*
|
|
262
|
+
* Removes a specific asset.
|
|
263
|
+
*
|
|
264
|
+
* @param {string} id - The ID of the asset to delete
|
|
265
|
+
* @throws {Error} If asset not found or doesn't belong to this component
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```typescript
|
|
269
|
+
* await assetsManager.deleteAssetById('123')
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
async deleteAssetById(id) {
|
|
273
|
+
const record = await this.db.getById(id);
|
|
274
|
+
if (!record) {
|
|
275
|
+
throw new Error(`Asset with ID ${id} not found`);
|
|
276
|
+
}
|
|
277
|
+
// Verify this asset belongs to our component
|
|
278
|
+
const config = this.getConfiguration();
|
|
279
|
+
if (record.name !== config.name) {
|
|
280
|
+
throw new Error(`Asset ${id} does not belong to component ${config.name}`);
|
|
281
|
+
}
|
|
282
|
+
await this.db.delete(id);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Delete latest asset (simplified)
|
|
286
|
+
*
|
|
287
|
+
* Removes the most recently uploaded asset for this component type.
|
|
288
|
+
*
|
|
289
|
+
* @throws {Error} If no assets exist to delete
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* await assetsManager.deleteLatestAsset()
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
async deleteLatestAsset() {
|
|
297
|
+
const config = this.getConfiguration();
|
|
298
|
+
const record = await this.db.getLatestByName(config.name);
|
|
299
|
+
if (record) {
|
|
300
|
+
await this.db.delete(record.id.toString());
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Get endpoints following the framework pattern
|
|
305
|
+
*/
|
|
306
|
+
/**
|
|
307
|
+
* Get HTTP endpoints exposed by this assets manager.
|
|
308
|
+
*
|
|
309
|
+
* Returns the standard CRUD endpoints following the framework pattern.
|
|
310
|
+
*
|
|
311
|
+
* @returns {Array} Array of endpoint descriptors with methods, paths, and handlers
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* // For a manager with assetType: 'gltf', provides:
|
|
316
|
+
* GET /gltf - Get all assets
|
|
317
|
+
* POST /gltf/upload - Upload new asset
|
|
318
|
+
* GET /gltf/123 - Get specific asset
|
|
319
|
+
* PUT /gltf/123 - Update asset metadata
|
|
320
|
+
* GET /gltf/123/download - Download asset
|
|
321
|
+
* DELETE /gltf/123 - Delete asset
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
getEndpoints() {
|
|
325
|
+
const config = this.getConfiguration();
|
|
326
|
+
return [
|
|
327
|
+
{
|
|
328
|
+
method: 'get',
|
|
329
|
+
path: `/${config.name}`,
|
|
330
|
+
handler: this.retrieve.bind(this),
|
|
331
|
+
responseType: 'application/json',
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
method: 'post',
|
|
335
|
+
path: `/${config.name}/upload`,
|
|
336
|
+
handler: this.handleUpload.bind(this),
|
|
337
|
+
responseType: 'application/json',
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
method: 'get',
|
|
341
|
+
path: `/${config.name}/:id`,
|
|
342
|
+
handler: this.handleGetAsset.bind(this),
|
|
343
|
+
responseType: config.contentType,
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
method: 'put',
|
|
347
|
+
path: `/${config.name}/:id`,
|
|
348
|
+
handler: this.handleUpdate.bind(this),
|
|
349
|
+
responseType: 'application/json',
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
method: 'get',
|
|
353
|
+
path: `/${config.name}/:id/download`,
|
|
354
|
+
handler: this.handleDownload.bind(this),
|
|
355
|
+
responseType: config.contentType,
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
method: 'delete',
|
|
359
|
+
path: `/${config.name}/:id`,
|
|
360
|
+
handler: this.handleDelete.bind(this),
|
|
361
|
+
responseType: 'application/json',
|
|
362
|
+
}
|
|
363
|
+
];
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Handle upload endpoint
|
|
367
|
+
*/
|
|
368
|
+
async handleUpload(req) {
|
|
369
|
+
try {
|
|
370
|
+
const { description, source, owner_id, filename } = req.body;
|
|
371
|
+
const file = req.file?.buffer;
|
|
372
|
+
if (!file || !description || !source || !owner_id || !filename) {
|
|
373
|
+
return {
|
|
374
|
+
status: 400,
|
|
375
|
+
content: JSON.stringify({
|
|
376
|
+
error: 'Missing required fields: description, source, owner_id, filename, file'
|
|
377
|
+
}),
|
|
378
|
+
headers: { 'Content-Type': 'application/json' }
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
await this.uploadAsset({
|
|
382
|
+
description,
|
|
383
|
+
source,
|
|
384
|
+
owner_id,
|
|
385
|
+
filename,
|
|
386
|
+
file
|
|
387
|
+
});
|
|
388
|
+
return {
|
|
389
|
+
status: 200,
|
|
390
|
+
content: JSON.stringify({ message: 'Asset uploaded successfully' }),
|
|
391
|
+
headers: { 'Content-Type': 'application/json' }
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
return {
|
|
396
|
+
status: 500,
|
|
397
|
+
content: JSON.stringify({
|
|
398
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
399
|
+
}),
|
|
400
|
+
headers: { 'Content-Type': 'application/json' }
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Handle update endpoint (PUT).
|
|
406
|
+
*
|
|
407
|
+
* Updates metadata for a specific asset by ID.
|
|
408
|
+
*
|
|
409
|
+
* @param {any} req - HTTP request object with params.id and body containing updates
|
|
410
|
+
* @returns {Promise<DataResponse>} HTTP response
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```typescript
|
|
414
|
+
* // PUT /gltf/123
|
|
415
|
+
* // Body: { "description": "Updated model", "source": "https://new-source.com" }
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
418
|
+
async handleUpdate(req) {
|
|
419
|
+
try {
|
|
420
|
+
const { id } = req.params || {};
|
|
421
|
+
const { description, source } = req.body || {};
|
|
422
|
+
if (!id) {
|
|
423
|
+
return {
|
|
424
|
+
status: 400,
|
|
425
|
+
content: JSON.stringify({
|
|
426
|
+
error: 'Asset ID is required'
|
|
427
|
+
}),
|
|
428
|
+
headers: { 'Content-Type': 'application/json' }
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
if (!description && !source) {
|
|
432
|
+
return {
|
|
433
|
+
status: 400,
|
|
434
|
+
content: JSON.stringify({
|
|
435
|
+
error: 'At least one field (description or source) must be provided for update'
|
|
436
|
+
}),
|
|
437
|
+
headers: { 'Content-Type': 'application/json' }
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
const updates = {};
|
|
441
|
+
if (description !== undefined)
|
|
442
|
+
updates.description = description;
|
|
443
|
+
if (source !== undefined)
|
|
444
|
+
updates.source = source;
|
|
445
|
+
await this.updateAssetMetadata(id, updates);
|
|
446
|
+
return {
|
|
447
|
+
status: 200,
|
|
448
|
+
content: JSON.stringify({ message: 'Asset metadata updated successfully' }),
|
|
449
|
+
headers: { 'Content-Type': 'application/json' }
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
catch (error) {
|
|
453
|
+
return {
|
|
454
|
+
status: 500,
|
|
455
|
+
content: JSON.stringify({
|
|
456
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
457
|
+
}),
|
|
458
|
+
headers: { 'Content-Type': 'application/json' }
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Handle get asset endpoint (GET).
|
|
464
|
+
*
|
|
465
|
+
* Returns the file content of a specific asset by ID for display/use in front-end.
|
|
466
|
+
* No download headers - just the raw file content.
|
|
467
|
+
*
|
|
468
|
+
* @param {any} req - HTTP request object with params.id
|
|
469
|
+
* @returns {Promise<DataResponse>} HTTP response with file content
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```typescript
|
|
473
|
+
* // GET /gltf/123
|
|
474
|
+
* // Returns the .glb file content for display in 3D viewer
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
async handleGetAsset(req) {
|
|
478
|
+
try {
|
|
479
|
+
const { id } = req.params || {};
|
|
480
|
+
if (!id) {
|
|
481
|
+
return {
|
|
482
|
+
status: 400,
|
|
483
|
+
content: JSON.stringify({
|
|
484
|
+
error: 'Asset ID is required'
|
|
485
|
+
}),
|
|
486
|
+
headers: { 'Content-Type': 'application/json' }
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
const asset = await this.getAssetById(id);
|
|
490
|
+
if (!asset) {
|
|
491
|
+
return {
|
|
492
|
+
status: 404,
|
|
493
|
+
content: 'Asset not found',
|
|
494
|
+
headers: { 'Content-Type': 'text/plain' }
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
// Verify this asset belongs to our component
|
|
498
|
+
const config = this.getConfiguration();
|
|
499
|
+
if (asset.name !== config.name) {
|
|
500
|
+
return {
|
|
501
|
+
status: 404,
|
|
502
|
+
content: 'Asset not found',
|
|
503
|
+
headers: { 'Content-Type': 'text/plain' }
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
// Get the file content
|
|
507
|
+
const fileContent = await asset.data();
|
|
508
|
+
return {
|
|
509
|
+
status: 200,
|
|
510
|
+
content: fileContent,
|
|
511
|
+
headers: {
|
|
512
|
+
'Content-Type': config.contentType
|
|
513
|
+
// No Content-Disposition - browser will display/use the file
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
return {
|
|
519
|
+
status: 500,
|
|
520
|
+
content: JSON.stringify({
|
|
521
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
522
|
+
}),
|
|
523
|
+
headers: { 'Content-Type': 'application/json' }
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Handle download endpoint (GET).
|
|
529
|
+
*
|
|
530
|
+
* Downloads the file content of a specific asset by ID with download headers.
|
|
531
|
+
* Forces browser to download the file rather than display it.
|
|
532
|
+
*
|
|
533
|
+
* @param {any} req - HTTP request object with params.id
|
|
534
|
+
* @returns {Promise<DataResponse>} HTTP response with file content and download headers
|
|
535
|
+
*
|
|
536
|
+
* @example
|
|
537
|
+
* ```typescript
|
|
538
|
+
* // GET /gltf/123/download
|
|
539
|
+
* // Returns the .glb file with download headers - browser will save it
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
async handleDownload(req) {
|
|
543
|
+
try {
|
|
544
|
+
const { id } = req.params || {};
|
|
545
|
+
if (!id) {
|
|
546
|
+
return {
|
|
547
|
+
status: 400,
|
|
548
|
+
content: JSON.stringify({
|
|
549
|
+
error: 'Asset ID is required'
|
|
550
|
+
}),
|
|
551
|
+
headers: { 'Content-Type': 'application/json' }
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
const asset = await this.getAssetById(id);
|
|
555
|
+
if (!asset) {
|
|
556
|
+
return {
|
|
557
|
+
status: 404,
|
|
558
|
+
content: 'Asset not found',
|
|
559
|
+
headers: { 'Content-Type': 'text/plain' }
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
// Verify this asset belongs to our component
|
|
563
|
+
const config = this.getConfiguration();
|
|
564
|
+
if (asset.name !== config.name) {
|
|
565
|
+
return {
|
|
566
|
+
status: 404,
|
|
567
|
+
content: 'Asset not found',
|
|
568
|
+
headers: { 'Content-Type': 'text/plain' }
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
// Get the file content
|
|
572
|
+
const fileContent = await asset.data();
|
|
573
|
+
// Get original filename from asset metadata
|
|
574
|
+
const filename = asset.filename || `asset_${id}`;
|
|
575
|
+
return {
|
|
576
|
+
status: 200,
|
|
577
|
+
content: fileContent,
|
|
578
|
+
headers: {
|
|
579
|
+
'Content-Type': config.contentType,
|
|
580
|
+
'Content-Disposition': `attachment; filename="${filename}"`
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
catch (error) {
|
|
585
|
+
return {
|
|
586
|
+
status: 500,
|
|
587
|
+
content: JSON.stringify({
|
|
588
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
589
|
+
}),
|
|
590
|
+
headers: { 'Content-Type': 'application/json' }
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Handle delete endpoint (DELETE).
|
|
596
|
+
*
|
|
597
|
+
* Deletes a specific asset by ID.
|
|
598
|
+
*
|
|
599
|
+
* @param {any} req - HTTP request object with params.id
|
|
600
|
+
* @returns {Promise<DataResponse>} HTTP response
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* // DELETE /gltf/123
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
async handleDelete(req) {
|
|
608
|
+
try {
|
|
609
|
+
const { id } = req.params || {};
|
|
610
|
+
if (!id) {
|
|
611
|
+
return {
|
|
612
|
+
status: 400,
|
|
613
|
+
content: JSON.stringify({
|
|
614
|
+
error: 'Asset ID is required'
|
|
615
|
+
}),
|
|
616
|
+
headers: { 'Content-Type': 'application/json' }
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
await this.deleteAssetById(id);
|
|
620
|
+
return {
|
|
621
|
+
status: 200,
|
|
622
|
+
content: JSON.stringify({ message: 'Asset deleted successfully' }),
|
|
623
|
+
headers: { 'Content-Type': 'application/json' }
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
catch (error) {
|
|
627
|
+
return {
|
|
628
|
+
status: 500,
|
|
629
|
+
content: JSON.stringify({
|
|
630
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
631
|
+
}),
|
|
632
|
+
headers: { 'Content-Type': 'application/json' }
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
//# sourceMappingURL=assets_manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets_manager.js","sourceRoot":"","sources":["../../src/components/assets_manager.ts"],"names":[],"mappings":"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"}
|