digitaltwin-core 0.14.2 → 1.0.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.
Files changed (227) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +494 -359
  3. package/dist/auth/apisix_parser.d.ts +141 -0
  4. package/dist/auth/apisix_parser.d.ts.map +1 -0
  5. package/dist/auth/apisix_parser.js +161 -0
  6. package/dist/auth/apisix_parser.js.map +1 -0
  7. package/dist/auth/auth_config.d.ts +126 -0
  8. package/dist/auth/auth_config.d.ts.map +1 -0
  9. package/dist/auth/auth_config.js +169 -0
  10. package/dist/auth/auth_config.js.map +1 -0
  11. package/dist/auth/auth_provider.d.ts +118 -0
  12. package/dist/auth/auth_provider.d.ts.map +1 -0
  13. package/dist/auth/auth_provider.js +8 -0
  14. package/dist/auth/auth_provider.js.map +1 -0
  15. package/dist/auth/auth_provider_factory.d.ts +91 -0
  16. package/dist/auth/auth_provider_factory.d.ts.map +1 -0
  17. package/dist/auth/auth_provider_factory.js +146 -0
  18. package/dist/auth/auth_provider_factory.js.map +1 -0
  19. package/dist/auth/index.d.ts +8 -0
  20. package/dist/auth/index.d.ts.map +1 -0
  21. package/dist/auth/index.js +7 -0
  22. package/dist/auth/index.js.map +1 -0
  23. package/dist/auth/providers/gateway_auth_provider.d.ts +78 -0
  24. package/dist/auth/providers/gateway_auth_provider.d.ts.map +1 -0
  25. package/dist/auth/providers/gateway_auth_provider.js +109 -0
  26. package/dist/auth/providers/gateway_auth_provider.js.map +1 -0
  27. package/dist/auth/providers/index.d.ts +4 -0
  28. package/dist/auth/providers/index.d.ts.map +1 -0
  29. package/dist/auth/providers/index.js +4 -0
  30. package/dist/auth/providers/index.js.map +1 -0
  31. package/dist/auth/providers/jwt_auth_provider.d.ts +91 -0
  32. package/dist/auth/providers/jwt_auth_provider.d.ts.map +1 -0
  33. package/dist/auth/providers/jwt_auth_provider.js +204 -0
  34. package/dist/auth/providers/jwt_auth_provider.js.map +1 -0
  35. package/dist/auth/providers/no_auth_provider.d.ts +61 -0
  36. package/dist/auth/providers/no_auth_provider.d.ts.map +1 -0
  37. package/dist/auth/providers/no_auth_provider.js +76 -0
  38. package/dist/auth/providers/no_auth_provider.js.map +1 -0
  39. package/dist/auth/types.d.ts +100 -0
  40. package/dist/auth/types.d.ts.map +1 -0
  41. package/dist/auth/types.js +2 -0
  42. package/dist/auth/types.js.map +1 -0
  43. package/dist/auth/user_service.d.ts +86 -0
  44. package/dist/auth/user_service.d.ts.map +1 -0
  45. package/dist/auth/user_service.js +237 -0
  46. package/dist/auth/user_service.js.map +1 -0
  47. package/dist/components/assets_manager.d.ts +662 -0
  48. package/dist/components/assets_manager.d.ts.map +1 -0
  49. package/dist/components/assets_manager.js +1537 -0
  50. package/dist/components/assets_manager.js.map +1 -0
  51. package/dist/components/async_upload.d.ts +20 -0
  52. package/dist/components/async_upload.d.ts.map +1 -0
  53. package/dist/components/async_upload.js +10 -0
  54. package/dist/components/async_upload.js.map +1 -0
  55. package/dist/components/collector.d.ts +203 -0
  56. package/dist/components/collector.d.ts.map +1 -0
  57. package/dist/components/collector.js +214 -0
  58. package/dist/components/collector.js.map +1 -0
  59. package/dist/components/custom_table_manager.d.ts +503 -0
  60. package/dist/components/custom_table_manager.d.ts.map +1 -0
  61. package/dist/components/custom_table_manager.js +1023 -0
  62. package/dist/components/custom_table_manager.js.map +1 -0
  63. package/dist/components/global_assets_handler.d.ts +63 -0
  64. package/dist/components/global_assets_handler.d.ts.map +1 -0
  65. package/dist/components/global_assets_handler.js +127 -0
  66. package/dist/components/global_assets_handler.js.map +1 -0
  67. package/dist/components/handler.d.ts +104 -0
  68. package/dist/components/handler.d.ts.map +1 -0
  69. package/dist/components/handler.js +110 -0
  70. package/dist/components/handler.js.map +1 -0
  71. package/dist/components/harvester.d.ts +182 -0
  72. package/dist/components/harvester.d.ts.map +1 -0
  73. package/dist/components/harvester.js +406 -0
  74. package/dist/components/harvester.js.map +1 -0
  75. package/dist/components/index.d.ts +11 -0
  76. package/dist/components/index.d.ts.map +1 -0
  77. package/dist/components/index.js +9 -0
  78. package/dist/components/index.js.map +1 -0
  79. package/dist/components/interfaces.d.ts +126 -0
  80. package/dist/components/interfaces.d.ts.map +1 -0
  81. package/dist/components/interfaces.js +8 -0
  82. package/dist/components/interfaces.js.map +1 -0
  83. package/dist/components/map_manager.d.ts +61 -0
  84. package/dist/components/map_manager.d.ts.map +1 -0
  85. package/dist/components/map_manager.js +242 -0
  86. package/dist/components/map_manager.js.map +1 -0
  87. package/dist/components/tileset_manager.d.ts +125 -0
  88. package/dist/components/tileset_manager.d.ts.map +1 -0
  89. package/dist/components/tileset_manager.js +623 -0
  90. package/dist/components/tileset_manager.js.map +1 -0
  91. package/dist/components/types.d.ts +226 -0
  92. package/dist/components/types.d.ts.map +1 -0
  93. package/dist/components/types.js +8 -0
  94. package/dist/components/types.js.map +1 -0
  95. package/dist/database/adapters/knex_database_adapter.d.ts +97 -0
  96. package/dist/database/adapters/knex_database_adapter.d.ts.map +1 -0
  97. package/dist/database/adapters/knex_database_adapter.js +729 -0
  98. package/dist/database/adapters/knex_database_adapter.js.map +1 -0
  99. package/dist/database/database_adapter.d.ts +262 -0
  100. package/dist/database/database_adapter.d.ts.map +1 -0
  101. package/dist/database/database_adapter.js +46 -0
  102. package/dist/database/database_adapter.js.map +1 -0
  103. package/dist/engine/digital_twin_engine.d.ts +295 -0
  104. package/dist/engine/digital_twin_engine.d.ts.map +1 -0
  105. package/dist/engine/digital_twin_engine.js +907 -0
  106. package/dist/engine/digital_twin_engine.js.map +1 -0
  107. package/dist/engine/endpoints.d.ts +47 -0
  108. package/dist/engine/endpoints.d.ts.map +1 -0
  109. package/dist/engine/endpoints.js +88 -0
  110. package/dist/engine/endpoints.js.map +1 -0
  111. package/dist/engine/error_handler.d.ts +20 -0
  112. package/dist/engine/error_handler.d.ts.map +1 -0
  113. package/dist/engine/error_handler.js +69 -0
  114. package/dist/engine/error_handler.js.map +1 -0
  115. package/dist/engine/events.d.ts +93 -0
  116. package/dist/engine/events.d.ts.map +1 -0
  117. package/dist/engine/events.js +71 -0
  118. package/dist/engine/events.js.map +1 -0
  119. package/dist/engine/health.d.ts +112 -0
  120. package/dist/engine/health.d.ts.map +1 -0
  121. package/dist/engine/health.js +190 -0
  122. package/dist/engine/health.js.map +1 -0
  123. package/dist/engine/initializer.d.ts +62 -0
  124. package/dist/engine/initializer.d.ts.map +1 -0
  125. package/dist/engine/initializer.js +108 -0
  126. package/dist/engine/initializer.js.map +1 -0
  127. package/dist/engine/queue_manager.d.ts +87 -0
  128. package/dist/engine/queue_manager.d.ts.map +1 -0
  129. package/dist/engine/queue_manager.js +196 -0
  130. package/dist/engine/queue_manager.js.map +1 -0
  131. package/dist/engine/scheduler.d.ts +30 -0
  132. package/dist/engine/scheduler.d.ts.map +1 -0
  133. package/dist/engine/scheduler.js +378 -0
  134. package/dist/engine/scheduler.js.map +1 -0
  135. package/dist/engine/upload_processor.d.ts +36 -0
  136. package/dist/engine/upload_processor.d.ts.map +1 -0
  137. package/dist/engine/upload_processor.js +113 -0
  138. package/dist/engine/upload_processor.js.map +1 -0
  139. package/dist/env/env.d.ts +134 -0
  140. package/dist/env/env.d.ts.map +1 -0
  141. package/dist/env/env.js +177 -0
  142. package/dist/env/env.js.map +1 -0
  143. package/dist/errors/index.d.ts +94 -0
  144. package/dist/errors/index.d.ts.map +1 -0
  145. package/dist/errors/index.js +149 -0
  146. package/dist/errors/index.js.map +1 -0
  147. package/dist/index.d.ts +55 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +65 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/openapi/generator.d.ts +93 -0
  152. package/dist/openapi/generator.d.ts.map +1 -0
  153. package/dist/openapi/generator.js +293 -0
  154. package/dist/openapi/generator.js.map +1 -0
  155. package/dist/openapi/index.d.ts +9 -0
  156. package/dist/openapi/index.d.ts.map +1 -0
  157. package/dist/openapi/index.js +9 -0
  158. package/dist/openapi/index.js.map +1 -0
  159. package/dist/openapi/types.d.ts +182 -0
  160. package/dist/openapi/types.d.ts.map +1 -0
  161. package/dist/openapi/types.js +16 -0
  162. package/dist/openapi/types.js.map +1 -0
  163. package/dist/storage/adapters/local_storage_service.d.ts +57 -0
  164. package/dist/storage/adapters/local_storage_service.d.ts.map +1 -0
  165. package/dist/storage/adapters/local_storage_service.js +132 -0
  166. package/dist/storage/adapters/local_storage_service.js.map +1 -0
  167. package/dist/storage/adapters/ovh_storage_service.d.ts +72 -0
  168. package/dist/storage/adapters/ovh_storage_service.d.ts.map +1 -0
  169. package/dist/storage/adapters/ovh_storage_service.js +205 -0
  170. package/dist/storage/adapters/ovh_storage_service.js.map +1 -0
  171. package/dist/storage/storage_factory.d.ts +14 -0
  172. package/dist/storage/storage_factory.d.ts.map +1 -0
  173. package/dist/storage/storage_factory.js +43 -0
  174. package/dist/storage/storage_factory.js.map +1 -0
  175. package/dist/storage/storage_service.d.ts +163 -0
  176. package/dist/storage/storage_service.d.ts.map +1 -0
  177. package/dist/storage/storage_service.js +58 -0
  178. package/dist/storage/storage_service.js.map +1 -0
  179. package/dist/types/data_record.d.ts +123 -0
  180. package/dist/types/data_record.d.ts.map +1 -0
  181. package/dist/types/data_record.js +8 -0
  182. package/dist/types/data_record.js.map +1 -0
  183. package/dist/utils/graceful_shutdown.d.ts +44 -0
  184. package/dist/utils/graceful_shutdown.d.ts.map +1 -0
  185. package/dist/utils/graceful_shutdown.js +79 -0
  186. package/dist/utils/graceful_shutdown.js.map +1 -0
  187. package/dist/utils/http_responses.d.ts +175 -0
  188. package/dist/utils/http_responses.d.ts.map +1 -0
  189. package/dist/utils/http_responses.js +216 -0
  190. package/dist/utils/http_responses.js.map +1 -0
  191. package/dist/utils/index.d.ts +8 -0
  192. package/dist/utils/index.d.ts.map +1 -0
  193. package/dist/utils/index.js +6 -0
  194. package/dist/utils/index.js.map +1 -0
  195. package/dist/utils/logger.d.ts +74 -0
  196. package/dist/utils/logger.d.ts.map +1 -0
  197. package/dist/utils/logger.js +92 -0
  198. package/dist/utils/logger.js.map +1 -0
  199. package/dist/utils/map_to_data_record.d.ts +10 -0
  200. package/dist/utils/map_to_data_record.d.ts.map +1 -0
  201. package/dist/utils/map_to_data_record.js +36 -0
  202. package/dist/utils/map_to_data_record.js.map +1 -0
  203. package/dist/utils/safe_async.d.ts +50 -0
  204. package/dist/utils/safe_async.d.ts.map +1 -0
  205. package/dist/utils/safe_async.js +90 -0
  206. package/dist/utils/safe_async.js.map +1 -0
  207. package/dist/utils/servable_endpoint.d.ts +63 -0
  208. package/dist/utils/servable_endpoint.d.ts.map +1 -0
  209. package/dist/utils/servable_endpoint.js +67 -0
  210. package/dist/utils/servable_endpoint.js.map +1 -0
  211. package/dist/utils/zip_utils.d.ts +66 -0
  212. package/dist/utils/zip_utils.d.ts.map +1 -0
  213. package/dist/utils/zip_utils.js +169 -0
  214. package/dist/utils/zip_utils.js.map +1 -0
  215. package/dist/validation/index.d.ts +3 -0
  216. package/dist/validation/index.d.ts.map +1 -0
  217. package/dist/validation/index.js +7 -0
  218. package/dist/validation/index.js.map +1 -0
  219. package/dist/validation/schemas.d.ts +273 -0
  220. package/dist/validation/schemas.d.ts.map +1 -0
  221. package/dist/validation/schemas.js +82 -0
  222. package/dist/validation/schemas.js.map +1 -0
  223. package/dist/validation/validate.d.ts +49 -0
  224. package/dist/validation/validate.d.ts.map +1 -0
  225. package/dist/validation/validate.js +110 -0
  226. package/dist/validation/validate.js.map +1 -0
  227. package/package.json +23 -13
@@ -0,0 +1,205 @@
1
+ /**
2
+ * OVH Object Storage implementation of StorageService
3
+ * via S3-compatible API using @aws-sdk/client-s3
4
+ */
5
+ import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, DeleteObjectsCommand, ListObjectsV2Command, PutBucketCorsCommand, ObjectCannedACL } from '@aws-sdk/client-s3';
6
+ import { StorageService } from '../storage_service.js';
7
+ import { safeAsync } from '../../utils/safe_async.js';
8
+ import { Logger } from '../../utils/logger.js';
9
+ const logger = new Logger('OvhS3Storage');
10
+ export class OvhS3StorageService extends StorageService {
11
+ #s3;
12
+ #bucket;
13
+ #endpoint;
14
+ constructor(config) {
15
+ super();
16
+ this.#bucket = config.bucket;
17
+ this.#endpoint = config.endpoint;
18
+ this.#s3 = new S3Client({
19
+ endpoint: config.endpoint,
20
+ region: config.region ?? 'gra',
21
+ credentials: {
22
+ accessKeyId: config.accessKey,
23
+ secretAccessKey: config.secretKey
24
+ },
25
+ forcePathStyle: false,
26
+ // Match Python boto3 config for OVH compatibility
27
+ requestChecksumCalculation: 'WHEN_REQUIRED',
28
+ responseChecksumValidation: 'WHEN_REQUIRED'
29
+ });
30
+ }
31
+ /**
32
+ * Uploads a file to the OVH S3-compatible object storage.
33
+ * @param buffer - File contents to upload
34
+ * @param collectorName - Folder/prefix to store under
35
+ * @param extension - Optional file extension (e.g. 'json')
36
+ * @returns The relative path (key) of the stored object
37
+ */
38
+ async save(buffer, collectorName, extension) {
39
+ const now = new Date();
40
+ const timestamp = now.toISOString().replace(/[:.]/g, '-');
41
+ const key = `${collectorName || 'default'}/${timestamp}${extension ? '.' + extension : ''}`;
42
+ await this.#s3.send(new PutObjectCommand({
43
+ Bucket: this.#bucket,
44
+ Key: key,
45
+ Body: buffer,
46
+ ACL: ObjectCannedACL.private
47
+ }));
48
+ return key;
49
+ }
50
+ /**
51
+ * Downloads and returns a stored object as a Buffer.
52
+ * @param relativePath - The key/path of the object to retrieve
53
+ * @returns The object contents as a Buffer
54
+ */
55
+ async retrieve(relativePath) {
56
+ const res = await this.#s3.send(new GetObjectCommand({
57
+ Bucket: this.#bucket,
58
+ Key: relativePath
59
+ }));
60
+ const chunks = [];
61
+ const stream = res.Body;
62
+ for await (const chunk of stream) {
63
+ chunks.push(Buffer.from(chunk));
64
+ }
65
+ return Buffer.concat(chunks);
66
+ }
67
+ /**
68
+ * Deletes an object from the storage bucket.
69
+ * @param relativePath - The key/path of the object to delete
70
+ */
71
+ async delete(relativePath) {
72
+ await this.#s3.send(new DeleteObjectCommand({
73
+ Bucket: this.#bucket,
74
+ Key: relativePath
75
+ }));
76
+ }
77
+ /**
78
+ * Uploads a file to OVH S3 at a specific path (preserves filename).
79
+ * Unlike save(), this method does not auto-generate a timestamp filename.
80
+ * Files are uploaded with public-read ACL for direct access (e.g., Cesium tilesets).
81
+ * @param buffer - File contents to upload
82
+ * @param relativePath - Full relative path including filename (e.g., 'tilesets/123/tileset.json')
83
+ * @returns The same relative path that was provided
84
+ */
85
+ async saveWithPath(buffer, relativePath) {
86
+ await this.#s3.send(new PutObjectCommand({
87
+ Bucket: this.#bucket,
88
+ Key: relativePath,
89
+ Body: buffer,
90
+ ACL: ObjectCannedACL.public_read
91
+ }));
92
+ return relativePath;
93
+ }
94
+ /**
95
+ * Deletes multiple objects in batch using S3 DeleteObjects API.
96
+ * Much faster than individual deletes - can delete up to 1000 objects per request.
97
+ * @param paths - Array of object keys to delete
98
+ */
99
+ async deleteBatch(paths) {
100
+ if (paths.length === 0)
101
+ return;
102
+ // S3 DeleteObjects supports max 1000 objects per request
103
+ const BATCH_SIZE = 1000;
104
+ const batches = [];
105
+ for (let i = 0; i < paths.length; i += BATCH_SIZE) {
106
+ batches.push(paths.slice(i, i + BATCH_SIZE));
107
+ }
108
+ // Process batches in parallel (but limit concurrency to avoid overwhelming the API)
109
+ const MAX_CONCURRENT = 5;
110
+ for (let i = 0; i < batches.length; i += MAX_CONCURRENT) {
111
+ const concurrentBatches = batches.slice(i, i + MAX_CONCURRENT);
112
+ await Promise.all(concurrentBatches.map((batch, index) => safeAsync(() => this.#s3.send(new DeleteObjectsCommand({
113
+ Bucket: this.#bucket,
114
+ Delete: {
115
+ Objects: batch.map(key => ({ Key: key })),
116
+ Quiet: true // Don't return info about each deleted object
117
+ }
118
+ })), `delete batch ${i + index + 1}/${batches.length}`, logger)));
119
+ }
120
+ }
121
+ /**
122
+ * Returns the public URL for a stored file.
123
+ * Constructs the OVH S3 public URL format: https://{bucket}.{endpoint_host}/{key}
124
+ * @param relativePath - The storage path/key of the file
125
+ * @returns The public URL to access the file directly
126
+ */
127
+ getPublicUrl(relativePath) {
128
+ // Extract host from endpoint (e.g., 'https://s3.gra.io.cloud.ovh.net' -> 's3.gra.io.cloud.ovh.net')
129
+ const endpointHost = this.#endpoint.replace(/^https?:\/\//, '');
130
+ // OVH S3 URL format: https://{bucket}.{endpoint_host}/{key}
131
+ return `https://${this.#bucket}.${endpointHost}/${relativePath}`;
132
+ }
133
+ /**
134
+ * Deletes all objects under a given prefix (folder).
135
+ * Lists objects by prefix and deletes them in batches for performance.
136
+ * @param prefix - The folder/prefix to delete (e.g., 'tilesets/123')
137
+ * @returns Number of files deleted
138
+ */
139
+ async deleteByPrefix(prefix) {
140
+ let totalDeleted = 0;
141
+ let continuationToken;
142
+ // Ensure prefix ends with '/' to avoid partial matches
143
+ const normalizedPrefix = prefix.endsWith('/') ? prefix : `${prefix}/`;
144
+ do {
145
+ // List objects with prefix (max 1000 per request)
146
+ const listResponse = await this.#s3.send(new ListObjectsV2Command({
147
+ Bucket: this.#bucket,
148
+ Prefix: normalizedPrefix,
149
+ ContinuationToken: continuationToken
150
+ }));
151
+ const objects = listResponse.Contents || [];
152
+ if (objects.length === 0)
153
+ break;
154
+ // Delete objects in batch
155
+ const keys = objects.map(obj => obj.Key).filter((key) => !!key);
156
+ if (keys.length > 0) {
157
+ await this.#s3.send(new DeleteObjectsCommand({
158
+ Bucket: this.#bucket,
159
+ Delete: {
160
+ Objects: keys.map(key => ({ Key: key })),
161
+ Quiet: true
162
+ }
163
+ }));
164
+ totalDeleted += keys.length;
165
+ }
166
+ continuationToken = listResponse.NextContinuationToken;
167
+ } while (continuationToken);
168
+ return totalDeleted;
169
+ }
170
+ /**
171
+ * Configure CORS settings for the bucket.
172
+ * Required for browser-based access to public files (e.g., Cesium loading tilesets).
173
+ * Should be called once during application startup.
174
+ *
175
+ * @param allowedOrigins - List of allowed origins (default: ['*'])
176
+ * @param allowedMethods - List of allowed HTTP methods (default: ['GET', 'HEAD'])
177
+ * @param allowedHeaders - List of allowed headers (default: ['*', 'Authorization'])
178
+ * @returns true if successful, false otherwise
179
+ */
180
+ async configureCors(allowedOrigins = ['*'], allowedMethods = ['GET', 'HEAD'], allowedHeaders = ['*', 'Authorization']) {
181
+ try {
182
+ await this.#s3.send(new PutBucketCorsCommand({
183
+ Bucket: this.#bucket,
184
+ CORSConfiguration: {
185
+ CORSRules: [
186
+ {
187
+ AllowedOrigins: allowedOrigins,
188
+ AllowedMethods: allowedMethods,
189
+ AllowedHeaders: allowedHeaders,
190
+ ExposeHeaders: ['ETag', 'Content-Length'],
191
+ MaxAgeSeconds: 3000
192
+ }
193
+ ]
194
+ }
195
+ }));
196
+ console.log('[OvhS3StorageService] CORS configured successfully');
197
+ return true;
198
+ }
199
+ catch (error) {
200
+ console.error('[OvhS3StorageService] Error configuring CORS:', error);
201
+ return false;
202
+ }
203
+ }
204
+ }
205
+ //# sourceMappingURL=ovh_storage_service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ovh_storage_service.js","sourceRoot":"","sources":["../../../src/storage/adapters/ovh_storage_service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { StorageService } from './storage_service.js';
2
+ export declare class StorageServiceFactory {
3
+ /**
4
+ * Creates and returns an instance of StorageService
5
+ * based on the STORAGE_CONFIG environment variable.
6
+ *
7
+ * - 'local': returns a LocalStorageService
8
+ * - 'ovh': returns an OvhS3StorageService
9
+ *
10
+ * @throws Error if STORAGE_CONFIG is not supported
11
+ */
12
+ static create(): StorageService;
13
+ }
14
+ //# sourceMappingURL=storage_factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage_factory.d.ts","sourceRoot":"","sources":["../../src/storage/storage_factory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAM1D,qBAAa,qBAAqB;IAC9B;;;;;;;;OAQG;IACH,MAAM,CAAC,MAAM,IAAI,cAAc;CAwBlC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Factory class for creating the appropriate StorageService
3
+ * implementation based on environment configuration.
4
+ */
5
+ import { Env } from '../env/env.js';
6
+ import { OvhS3StorageService } from './adapters/ovh_storage_service.js';
7
+ import { LocalStorageService } from './adapters/local_storage_service.js';
8
+ import { safeAsync } from '../utils/safe_async.js';
9
+ import { Logger } from '../utils/logger.js';
10
+ const logger = new Logger('StorageFactory');
11
+ export class StorageServiceFactory {
12
+ /**
13
+ * Creates and returns an instance of StorageService
14
+ * based on the STORAGE_CONFIG environment variable.
15
+ *
16
+ * - 'local': returns a LocalStorageService
17
+ * - 'ovh': returns an OvhS3StorageService
18
+ *
19
+ * @throws Error if STORAGE_CONFIG is not supported
20
+ */
21
+ static create() {
22
+ const env = Env.config;
23
+ switch (env.STORAGE_CONFIG) {
24
+ case 'local':
25
+ return new LocalStorageService(env.LOCAL_STORAGE_DIR || 'data');
26
+ case 'ovh': {
27
+ const ovhStorage = new OvhS3StorageService({
28
+ accessKey: env.OVH_ACCESS_KEY,
29
+ secretKey: env.OVH_SECRET_KEY,
30
+ endpoint: env.OVH_ENDPOINT,
31
+ bucket: env.OVH_BUCKET,
32
+ region: env.OVH_REGION ?? 'gra'
33
+ });
34
+ // Configure CORS for browser access (non-blocking)
35
+ safeAsync(() => ovhStorage.configureCors(), 'configure OVH CORS', logger);
36
+ return ovhStorage;
37
+ }
38
+ default:
39
+ throw new Error(`Unsupported STORAGE_CONFIG: ${env.STORAGE_CONFIG}`);
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=storage_factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage_factory.js","sourceRoot":"","sources":["../../src/storage/storage_factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AAEzE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAE3C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAA;AAE3C,MAAM,OAAO,qBAAqB;IAC9B;;;;;;;;OAQG;IACH,MAAM,CAAC,MAAM;QACT,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAA;QAEtB,QAAQ,GAAG,CAAC,cAAc,EAAE,CAAC;YACzB,KAAK,OAAO;gBACR,OAAO,IAAI,mBAAmB,CAAC,GAAG,CAAC,iBAAiB,IAAI,MAAM,CAAC,CAAA;YAEnE,KAAK,KAAK,CAAC,CAAC,CAAC;gBACT,MAAM,UAAU,GAAG,IAAI,mBAAmB,CAAC;oBACvC,SAAS,EAAE,GAAG,CAAC,cAAc;oBAC7B,SAAS,EAAE,GAAG,CAAC,cAAc;oBAC7B,QAAQ,EAAE,GAAG,CAAC,YAAY;oBAC1B,MAAM,EAAE,GAAG,CAAC,UAAU;oBACtB,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,KAAK;iBAClC,CAAC,CAAA;gBACF,mDAAmD;gBACnD,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,EAAE,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;gBACzE,OAAO,UAAU,CAAA;YACrB,CAAC;YAED;gBACI,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAA;QAC5E,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Abstract base class for storage service implementations.
3
+ *
4
+ * Defines the contract for persisting and retrieving binary data in the Digital Twin framework.
5
+ * Concrete implementations provide storage backends like local filesystem, AWS S3, Azure Blob, etc.
6
+ *
7
+ * @abstract
8
+ * @class StorageService
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Implement for specific storage backend
13
+ * class S3StorageService extends StorageService {
14
+ * async save(buffer: Buffer, collectorName: string, extension?: string): Promise<string> {
15
+ * // Upload to S3 bucket
16
+ * return 's3://bucket/path/to/file'
17
+ * }
18
+ *
19
+ * async retrieve(path: string): Promise<Buffer> {
20
+ * // Download from S3
21
+ * return buffer
22
+ * }
23
+ *
24
+ * async delete(path: string): Promise<void> {
25
+ * // Delete from S3
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ export declare abstract class StorageService {
31
+ /**
32
+ * Persists binary data and returns a unique identifier for retrieval.
33
+ *
34
+ * The storage implementation should ensure the returned path/URL is unique
35
+ * and can be used later to retrieve the exact same data.
36
+ *
37
+ * @abstract
38
+ * @param {Buffer} buffer - Binary data to store
39
+ * @param {string} collectorName - Component name for organizing storage (used as folder/prefix)
40
+ * @param {string} extension - Optional file extension for proper content handling
41
+ * @returns {Promise<string>} Unique storage identifier (path, URL, or key)
42
+ * @throws {Error} When storage operation fails
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const buffer = Buffer.from('{"temperature": 23.5}')
47
+ * const path = await storage.save(buffer, 'weather-sensor', 'json')
48
+ * // Returns: '/storage/weather-sensor/2024-01-15_14-30-00.json'
49
+ * ```
50
+ */
51
+ abstract save(buffer: Buffer, collectorName: string, extension?: string): Promise<string>;
52
+ /**
53
+ * Retrieves previously stored binary data.
54
+ *
55
+ * Uses the identifier returned by save() to fetch the original data.
56
+ *
57
+ * @abstract
58
+ * @param {string} path - Storage identifier from save() operation
59
+ * @returns {Promise<Buffer>} The original binary data
60
+ * @throws {Error} When file doesn't exist or retrieval fails
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const path = '/storage/weather-sensor/2024-01-15_14-30-00.json'
65
+ * const data = await storage.retrieve(path)
66
+ * const json = JSON.parse(data.toString())
67
+ * ```
68
+ */
69
+ abstract retrieve(path: string): Promise<Buffer>;
70
+ /**
71
+ * Removes stored data permanently.
72
+ *
73
+ * Deletes the data associated with the given storage identifier.
74
+ *
75
+ * @abstract
76
+ * @param {string} path - Storage identifier from save() operation
77
+ * @returns {Promise<void>}
78
+ * @throws {Error} When deletion fails or path doesn't exist
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const path = '/storage/weather-sensor/old-data.json'
83
+ * await storage.delete(path)
84
+ * ```
85
+ */
86
+ abstract delete(path: string): Promise<void>;
87
+ /**
88
+ * Persists binary data at a specific path (no auto-generated filename).
89
+ *
90
+ * Unlike save(), this method stores the file at the exact path specified,
91
+ * preserving the original filename and directory structure.
92
+ * Useful for extracting archives where file paths must be preserved.
93
+ *
94
+ * @param {Buffer} buffer - Binary data to store
95
+ * @param {string} relativePath - Full relative path including filename (e.g., 'tilesets/123/tileset.json')
96
+ * @returns {Promise<string>} The same path that was provided (for consistency)
97
+ * @throws {Error} When storage operation fails
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const buffer = Buffer.from('{"asset": {"version": "1.0"}}')
102
+ * const path = await storage.saveWithPath(buffer, 'tilesets/123/tileset.json')
103
+ * // Returns: 'tilesets/123/tileset.json'
104
+ * ```
105
+ */
106
+ abstract saveWithPath(buffer: Buffer, relativePath: string): Promise<string>;
107
+ /**
108
+ * Deletes multiple files in batch for better performance.
109
+ *
110
+ * Default implementation calls delete() sequentially, but storage backends
111
+ * can override this with optimized bulk delete operations (e.g., S3 DeleteObjects).
112
+ *
113
+ * @param {string[]} paths - Array of storage identifiers to delete
114
+ * @returns {Promise<void>}
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * await storage.deleteBatch([
119
+ * 'tilesets/123/tileset.json',
120
+ * 'tilesets/123/tile_0.b3dm',
121
+ * 'tilesets/123/tile_1.b3dm'
122
+ * ])
123
+ * ```
124
+ */
125
+ deleteBatch(paths: string[]): Promise<void>;
126
+ /**
127
+ * Returns the public URL for a stored file.
128
+ *
129
+ * For cloud storage (S3, OVH, Azure), this returns the direct HTTP URL.
130
+ * For local storage, this may return a relative path or throw an error.
131
+ *
132
+ * @abstract
133
+ * @param {string} relativePath - The storage path/key of the file
134
+ * @returns {string} The public URL to access the file directly
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const url = storage.getPublicUrl('tilesets/123/tileset.json')
139
+ * // Returns: 'https://bucket.s3.region.cloud.ovh.net/tilesets/123/tileset.json'
140
+ * ```
141
+ */
142
+ abstract getPublicUrl(relativePath: string): string;
143
+ /**
144
+ * Deletes all files under a given prefix/folder.
145
+ *
146
+ * This is more efficient than deleteBatch() when you don't know all file paths,
147
+ * as it lists objects by prefix and deletes them in bulk.
148
+ * Useful for deleting entire tilesets or component data.
149
+ *
150
+ * @abstract
151
+ * @param {string} prefix - The folder/prefix to delete (e.g., 'tilesets/123')
152
+ * @returns {Promise<number>} Number of files deleted
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const count = await storage.deleteByPrefix('tilesets/123')
157
+ * // Deletes all files starting with 'tilesets/123/'
158
+ * console.log(`Deleted ${count} files`)
159
+ * ```
160
+ */
161
+ abstract deleteByPrefix(prefix: string): Promise<number>;
162
+ }
163
+ //# sourceMappingURL=storage_service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage_service.d.ts","sourceRoot":"","sources":["../../src/storage/storage_service.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,8BAAsB,cAAc;IAChC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEzF;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEhD;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAE5C;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAE5E;;;;;;;;;;;;;;;;;OAiBG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjD;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAEnD;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAC3D"}
@@ -0,0 +1,58 @@
1
+ import { safeAsync } from '../utils/safe_async.js';
2
+ import { Logger } from '../utils/logger.js';
3
+ const logger = new Logger('StorageService');
4
+ /**
5
+ * Abstract base class for storage service implementations.
6
+ *
7
+ * Defines the contract for persisting and retrieving binary data in the Digital Twin framework.
8
+ * Concrete implementations provide storage backends like local filesystem, AWS S3, Azure Blob, etc.
9
+ *
10
+ * @abstract
11
+ * @class StorageService
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Implement for specific storage backend
16
+ * class S3StorageService extends StorageService {
17
+ * async save(buffer: Buffer, collectorName: string, extension?: string): Promise<string> {
18
+ * // Upload to S3 bucket
19
+ * return 's3://bucket/path/to/file'
20
+ * }
21
+ *
22
+ * async retrieve(path: string): Promise<Buffer> {
23
+ * // Download from S3
24
+ * return buffer
25
+ * }
26
+ *
27
+ * async delete(path: string): Promise<void> {
28
+ * // Delete from S3
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ export class StorageService {
34
+ /**
35
+ * Deletes multiple files in batch for better performance.
36
+ *
37
+ * Default implementation calls delete() sequentially, but storage backends
38
+ * can override this with optimized bulk delete operations (e.g., S3 DeleteObjects).
39
+ *
40
+ * @param {string[]} paths - Array of storage identifiers to delete
41
+ * @returns {Promise<void>}
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * await storage.deleteBatch([
46
+ * 'tilesets/123/tileset.json',
47
+ * 'tilesets/123/tile_0.b3dm',
48
+ * 'tilesets/123/tile_1.b3dm'
49
+ * ])
50
+ * ```
51
+ */
52
+ async deleteBatch(paths) {
53
+ // Default parallel implementation - subclasses can override with bulk operations
54
+ // Individual failures are logged but don't prevent other deletions
55
+ await Promise.all(paths.map(path => safeAsync(() => this.delete(path), `delete file ${path}`, logger)));
56
+ }
57
+ }
58
+ //# sourceMappingURL=storage_service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage_service.js","sourceRoot":"","sources":["../../src/storage/storage_service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAE3C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAgB,cAAc;IAiFhC;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,WAAW,CAAC,KAAe;QAC7B,iFAAiF;QACjF,mEAAmE;QACnE,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,eAAe,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IAC3G,CAAC;CAuCJ"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @fileoverview Data record type definition for digital twin data storage
3
+ *
4
+ * This module defines the standardized interface for data records used
5
+ * throughout the digital twin system for both streaming data and asset storage.
6
+ */
7
+ /**
8
+ * Standard data record interface for digital twin data storage.
9
+ *
10
+ * DataRecord provides a unified interface for all data stored in the digital twin system,
11
+ * from streaming sensor data to asset files. It supports both database metadata
12
+ * and file storage through a consistent API.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const record: DataRecord = {
17
+ * id: 12345,
18
+ * name: 'weather-station-001',
19
+ * date: new Date(),
20
+ * contentType: 'application/json',
21
+ * url: '/api/data/weather/12345',
22
+ * data: async () => Buffer.from(JSON.stringify(weatherData)),
23
+ * description: 'Weather data from station 001',
24
+ * source: 'https://api.weather.com/v1/current',
25
+ * owner_id: 123
26
+ * };
27
+ * ```
28
+ */
29
+ export interface DataRecord {
30
+ /** Unique identifier for this data record */
31
+ id: number;
32
+ /** Human-readable name or identifier for this record */
33
+ name: string;
34
+ /** Timestamp when this record was created or last updated */
35
+ date: Date;
36
+ /** MIME type of the data content (e.g., 'application/json', 'image/png') */
37
+ contentType: string;
38
+ /** URL or path where this record can be accessed */
39
+ url: string;
40
+ /**
41
+ * Function that returns the actual data content as a Buffer.
42
+ *
43
+ * This lazy-loading approach allows for efficient memory usage
44
+ * when working with large datasets or files.
45
+ *
46
+ * @returns Promise resolving to the data content as a Buffer
47
+ */
48
+ data: () => Promise<Buffer>;
49
+ /**
50
+ * Human-readable description of the asset.
51
+ *
52
+ * Used primarily by AssetsManager components to provide
53
+ * additional context about stored files and resources.
54
+ */
55
+ description?: string;
56
+ /**
57
+ * Source URL for data provenance.
58
+ *
59
+ * Records the original source of this data for traceability
60
+ * and debugging purposes. Used by AssetsManager components.
61
+ */
62
+ source?: string;
63
+ /**
64
+ * ID of the user who owns this asset.
65
+ *
66
+ * Enables access control and ownership tracking for
67
+ * asset management. Used by AssetsManager components.
68
+ */
69
+ owner_id?: number | null;
70
+ /**
71
+ * Original filename provided by the user.
72
+ *
73
+ * Preserves the original filename when assets are uploaded
74
+ * or imported. Used by AssetsManager components.
75
+ */
76
+ filename?: string;
77
+ /**
78
+ * Whether the asset is publicly accessible.
79
+ *
80
+ * Controls visibility of assets. If true, asset can be accessed
81
+ * by anyone. If false, only the owner can access it.
82
+ * Used by AssetsManager components for access control.
83
+ */
84
+ is_public?: boolean;
85
+ /**
86
+ * Public URL to tileset.json for Cesium loading.
87
+ * Cesium accesses files directly via this URL.
88
+ */
89
+ tileset_url?: string;
90
+ /**
91
+ * @deprecated No longer used. Kept for backward compatibility.
92
+ */
93
+ file_index?: {
94
+ /** List of files with their storage paths */
95
+ files: Array<{
96
+ /** Storage path for this file */
97
+ path: string;
98
+ /** Original filename */
99
+ name: string;
100
+ /** File size in bytes */
101
+ size?: number;
102
+ }>;
103
+ /** Main entry point file (e.g., 'tileset.json') */
104
+ root_file?: string;
105
+ };
106
+ /**
107
+ * Status of async upload processing.
108
+ * - 'pending': Job queued, waiting to start
109
+ * - 'processing': Job is running
110
+ * - 'completed': Job finished successfully
111
+ * - 'failed': Job failed with error
112
+ */
113
+ upload_status?: 'pending' | 'processing' | 'completed' | 'failed' | null;
114
+ /**
115
+ * Error message if upload failed.
116
+ */
117
+ upload_error?: string | null;
118
+ /**
119
+ * BullMQ job ID for tracking.
120
+ */
121
+ upload_job_id?: string | null;
122
+ }
123
+ //# sourceMappingURL=data_record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data_record.d.ts","sourceRoot":"","sources":["../../src/types/data_record.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,UAAU;IACvB,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAA;IAEV,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IAEZ,6DAA6D;IAC7D,IAAI,EAAE,IAAI,CAAA;IAEV,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAA;IAEnB,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAA;IAEX;;;;;;;OAOG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAI3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAExB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IAInB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAIpB;;OAEG;IACH,UAAU,CAAC,EAAE;QACT,6CAA6C;QAC7C,KAAK,EAAE,KAAK,CAAC;YACT,iCAAiC;YACjC,IAAI,EAAE,MAAM,CAAA;YACZ,wBAAwB;YACxB,IAAI,EAAE,MAAM,CAAA;YACZ,yBAAyB;YACzB,IAAI,CAAC,EAAE,MAAM,CAAA;SAChB,CAAC,CAAA;QACF,mDAAmD;QACnD,SAAS,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;IAID;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,IAAI,CAAA;IAExE;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAE5B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @fileoverview Data record type definition for digital twin data storage
3
+ *
4
+ * This module defines the standardized interface for data records used
5
+ * throughout the digital twin system for both streaming data and asset storage.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=data_record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data_record.js","sourceRoot":"","sources":["../../src/types/data_record.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}