@dudousxd/nestjs-agent 1.9.0 → 1.10.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.
@@ -0,0 +1,608 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/media/media-attachment-staging.ts
5
+ import { randomUUID } from "crypto";
6
+ import { publishMedia } from "@dudousxd/nestjs-media";
7
+ import { BadRequestException, ConflictException, Logger, NotImplementedException, PayloadTooLargeException, UnprocessableEntityException, UnsupportedMediaTypeException } from "@nestjs/common";
8
+
9
+ // src/media/media-attachments.options.ts
10
+ var DEFAULT_AGENT_MEDIA_COLLECTION = "agent-attachments";
11
+ var DEFAULT_AGENT_MEDIA_OWNER_TYPE = "agent-actor";
12
+ var DEFAULT_AGENT_MEDIA_URL_TTL_SECONDS = 7 * 24 * 60 * 60;
13
+ var DEFAULT_AGENT_MEDIA_TUS_BASE_PATH = "/media/uploads";
14
+
15
+ // src/media/media-attachment-staging.ts
16
+ var DEFAULT_MAX_BYTES = 20 * 1024 * 1024;
17
+ var DEFAULT_ALLOWED_CONTENT_TYPES = [
18
+ "image/png",
19
+ "image/jpeg",
20
+ "image/gif",
21
+ "image/webp",
22
+ "application/pdf",
23
+ "text/plain",
24
+ "text/csv"
25
+ ];
26
+ var MediaAttachmentStaging2 = class _MediaAttachmentStaging {
27
+ static {
28
+ __name(this, "MediaAttachmentStaging");
29
+ }
30
+ deps;
31
+ options;
32
+ logger = new Logger(_MediaAttachmentStaging.name);
33
+ collection;
34
+ ownerType;
35
+ maxBytes;
36
+ allowed;
37
+ now;
38
+ newId;
39
+ warnedInline = false;
40
+ constructor(deps, options) {
41
+ this.deps = deps;
42
+ this.options = options;
43
+ this.collection = options.collection ?? DEFAULT_AGENT_MEDIA_COLLECTION;
44
+ this.ownerType = options.ownerType ?? DEFAULT_AGENT_MEDIA_OWNER_TYPE;
45
+ this.maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
46
+ this.allowed = options.allowedContentTypes ?? DEFAULT_ALLOWED_CONTENT_TYPES;
47
+ this.now = options.clock ?? (() => /* @__PURE__ */ new Date());
48
+ this.newId = options.idGenerator ?? (() => randomUUID());
49
+ }
50
+ get diskName() {
51
+ return this.options.disk ?? this.deps.storage.defaultDisk;
52
+ }
53
+ /** Open a tus session for one file, owned by `actor`. Validation happens here, before any byte moves. */
54
+ async beginUpload(input) {
55
+ const uploads = this.deps.uploads;
56
+ if (uploads === null) {
57
+ throw new NotImplementedException("Resumable attachment uploads need MediaModule configured with `uploadSessions` and `tus`.");
58
+ }
59
+ this.validate(input.filename, input.contentType, input.size);
60
+ const id = this.newId();
61
+ const fileName = safeFileName(input.filename);
62
+ const path = this.pathFor(input.actor, id, fileName);
63
+ const session = await uploads.createUpload({
64
+ disk: this.diskName,
65
+ key: path,
66
+ size: input.size,
67
+ contentType: input.contentType,
68
+ metadata: {
69
+ agentMediaId: id
70
+ }
71
+ });
72
+ await this.saveRecord({
73
+ id,
74
+ actor: input.actor,
75
+ fileName,
76
+ mimeType: input.contentType,
77
+ size: input.size,
78
+ path,
79
+ state: {
80
+ status: "pending",
81
+ uploadId: session.id
82
+ }
83
+ });
84
+ const base = (this.options.tusBasePath ?? DEFAULT_AGENT_MEDIA_TUS_BASE_PATH).replace(/\/+$/, "");
85
+ return {
86
+ mediaId: id,
87
+ uploadId: session.id,
88
+ location: `${base}/${session.id}`
89
+ };
90
+ }
91
+ /**
92
+ * Confirm the bytes of a `beginUpload` landed and whole. `null` for an unknown or foreign id;
93
+ * `409` while the bytes are still missing; `422` (and the record dropped) when what arrived is
94
+ * not the size that was declared. Idempotent on a ready record.
95
+ */
96
+ async completeUpload(input) {
97
+ const record = await this.ownRecord(input.mediaId, input.actor);
98
+ if (record === null) return null;
99
+ const ready = await this.ensureReady(record);
100
+ if (ready === "missing") {
101
+ throw new ConflictException(`upload ${input.mediaId} has not finished`);
102
+ }
103
+ if (ready === "mismatch") {
104
+ await this.remove(record.id);
105
+ throw new UnprocessableEntityException(`upload ${input.mediaId} does not match its declared size`);
106
+ }
107
+ return this.toAttachment(ready, {
108
+ forModel: false
109
+ });
110
+ }
111
+ /** The actor drops one of their own attachments — aborting its upload if still in flight. */
112
+ async discard(input) {
113
+ const record = await this.ownRecord(input.mediaId, input.actor);
114
+ if (record === null) return false;
115
+ await this.remove(record.id);
116
+ return true;
117
+ }
118
+ /**
119
+ * Delete an attachment's bytes, its in-flight tus session and its record. NO ownership check —
120
+ * the host's sweep calls this for what `AgentService.collectableAttachments` returned.
121
+ */
122
+ async remove(mediaId) {
123
+ const record = await this.deps.store.find(mediaId);
124
+ if (record === null || !this.isOurs(record)) return;
125
+ const state = stateOf(record);
126
+ if (state.status === "pending" && state.uploadId !== void 0) {
127
+ await this.deps.uploads?.abort(state.uploadId).catch(() => void 0);
128
+ }
129
+ await this.deps.storage.disk(record.disk).delete(record.path).catch(() => void 0);
130
+ await this.deps.store.delete(record.id);
131
+ if (this.options.indexForRag === true && state.status === "ready") {
132
+ publishMedia("delete", {
133
+ id: record.id,
134
+ ownerType: record.ownerType,
135
+ ownerId: record.ownerId
136
+ });
137
+ }
138
+ }
139
+ async stage(input) {
140
+ const id = this.newId();
141
+ const fileName = safeFileName(input.filename);
142
+ const path = this.pathFor(input.actor, id, fileName);
143
+ await this.deps.storage.disk(this.diskName).put(path, input.data, {
144
+ contentType: input.contentType
145
+ });
146
+ const record = await this.saveRecord({
147
+ id,
148
+ actor: input.actor,
149
+ fileName,
150
+ mimeType: input.contentType,
151
+ size: input.sizeBytes,
152
+ path,
153
+ state: {
154
+ status: "ready"
155
+ }
156
+ });
157
+ this.announce(record);
158
+ return this.toAttachment(record, {
159
+ forModel: false
160
+ });
161
+ }
162
+ /**
163
+ * The attachment for `mediaId`, or `null` when it is unknown, not this actor's, or its bytes have
164
+ * not (fully) arrived. The actor may use media they own, and media a message in one of THEIR
165
+ * threads already carries (a fork, a regenerate) — never anything else.
166
+ */
167
+ async resolve(input) {
168
+ const record = await this.deps.store.find(input.mediaId);
169
+ if (record === null || !this.isOurs(record)) return null;
170
+ if (!await this.canUse(record, input.actor)) return null;
171
+ const ready = await this.ensureReady(record);
172
+ if (typeof ready === "string") return null;
173
+ return this.toAttachment(ready, {
174
+ forModel: true
175
+ });
176
+ }
177
+ async list(input) {
178
+ const records = await this.deps.store.listByOwner(this.ownerType, input.actor.id, this.collection);
179
+ const entries = records.map((record) => ({
180
+ mediaId: record.id,
181
+ name: record.fileName,
182
+ contentType: record.mimeType,
183
+ sizeBytes: record.size,
184
+ createdAt: new Date(record.createdAt).toISOString()
185
+ })).filter((entry) => input.stagedBefore === void 0 || entry.createdAt < input.stagedBefore).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
186
+ return input.limit === void 0 ? entries : entries.slice(0, input.limit);
187
+ }
188
+ validate(filename, contentType, size) {
189
+ if (typeof filename !== "string" || filename.trim().length === 0) {
190
+ throw new BadRequestException("filename is required");
191
+ }
192
+ if (typeof contentType !== "string" || !this.allowed.includes(contentType)) {
193
+ throw new UnsupportedMediaTypeException(`content type "${String(contentType)}" is not allowed (allowed: ${this.allowed.join(", ")})`);
194
+ }
195
+ if (typeof size !== "number" || !Number.isInteger(size) || size <= 0) {
196
+ throw new BadRequestException("size must be a positive integer byte count");
197
+ }
198
+ if (size > this.maxBytes) {
199
+ throw new PayloadTooLargeException(`file exceeds the ${this.maxBytes}-byte limit`);
200
+ }
201
+ }
202
+ pathFor(actor, id, fileName) {
203
+ return `${this.ownerType}/${encodeURIComponent(actor.id)}/${this.collection}/${id}/${fileName}`;
204
+ }
205
+ async saveRecord(input) {
206
+ const timestamp = this.now();
207
+ return this.deps.store.save({
208
+ id: input.id,
209
+ ownerType: this.ownerType,
210
+ ownerId: input.actor.id,
211
+ collection: this.collection,
212
+ name: stripExtension(input.fileName),
213
+ fileName: input.fileName,
214
+ mimeType: input.mimeType,
215
+ size: input.size,
216
+ disk: this.diskName,
217
+ path: input.path,
218
+ order: await this.deps.store.nextOrder(this.ownerType, input.actor.id, this.collection),
219
+ customProperties: {
220
+ agentAttachment: input.state
221
+ },
222
+ conversions: {},
223
+ createdAt: timestamp,
224
+ updatedAt: timestamp
225
+ });
226
+ }
227
+ isOurs(record) {
228
+ return record.ownerType === this.ownerType && record.collection === this.collection;
229
+ }
230
+ async ownRecord(mediaId, actor) {
231
+ const record = await this.deps.store.find(mediaId);
232
+ if (record === null || !this.isOurs(record) || record.ownerId !== actor.id) return null;
233
+ return record;
234
+ }
235
+ async canUse(record, actor) {
236
+ const allowed = await this.defaultAccess(record, actor);
237
+ const custom = this.options.canAccess;
238
+ return custom === void 0 ? allowed : await custom({
239
+ record,
240
+ actor,
241
+ allowed
242
+ }) === true;
243
+ }
244
+ async defaultAccess(record, actor) {
245
+ if (record.ownerId === actor.id) return true;
246
+ const referenced = this.deps.agentStore?.referencedMediaIds?.bind(this.deps.agentStore);
247
+ if (referenced === void 0) return false;
248
+ return (await referenced(actor.id, [
249
+ record.id
250
+ ])).includes(record.id);
251
+ }
252
+ /**
253
+ * A ready record as-is; a pending one promoted to ready once its bytes are on the disk at exactly
254
+ * the declared size. `'missing'` while they are not; `'mismatch'` when they arrived at another size.
255
+ */
256
+ async ensureReady(record) {
257
+ if (stateOf(record).status === "ready") return record;
258
+ const disk = this.deps.storage.disk(record.disk);
259
+ if (!await disk.exists(record.path)) return "missing";
260
+ const size = await disk.size(record.path);
261
+ if (size !== record.size || size > this.maxBytes) return "mismatch";
262
+ const ready = await this.deps.store.save({
263
+ ...record,
264
+ customProperties: {
265
+ ...record.customProperties,
266
+ agentAttachment: {
267
+ status: "ready"
268
+ }
269
+ },
270
+ updatedAt: this.now()
271
+ });
272
+ this.announce(ready);
273
+ return ready;
274
+ }
275
+ announce(record) {
276
+ if (this.options.indexForRag !== true) return;
277
+ publishMedia("attach", {
278
+ id: record.id,
279
+ ownerType: record.ownerType,
280
+ ownerId: record.ownerId,
281
+ collection: record.collection,
282
+ disk: record.disk,
283
+ path: record.path,
284
+ size: record.size,
285
+ mimeType: record.mimeType
286
+ });
287
+ }
288
+ /**
289
+ * `forModel: false` is what goes back to the uploader: never inline bytes (they already have the
290
+ * file), so an inline-only disk answers with an empty url there.
291
+ */
292
+ async toAttachment(record, { forModel }) {
293
+ const base = {
294
+ mediaId: record.id,
295
+ contentType: record.mimeType,
296
+ name: record.fileName
297
+ };
298
+ const disk = this.deps.storage.disk(record.disk);
299
+ if (this.options.resolveUrl !== void 0) {
300
+ return {
301
+ ...base,
302
+ url: await this.options.resolveUrl(record, {
303
+ disk
304
+ })
305
+ };
306
+ }
307
+ if (this.options.visibility === "public") {
308
+ return {
309
+ ...base,
310
+ url: await disk.url(record.path)
311
+ };
312
+ }
313
+ if (disk.capabilities.presign) {
314
+ const ttl = this.options.urlExpiresInSeconds ?? DEFAULT_AGENT_MEDIA_URL_TTL_SECONDS;
315
+ return {
316
+ ...base,
317
+ url: await disk.temporaryUrl(record.path, ttl, {
318
+ responseContentType: record.mimeType
319
+ })
320
+ };
321
+ }
322
+ if (!forModel) return {
323
+ ...base,
324
+ url: ""
325
+ };
326
+ if (!this.warnedInline) {
327
+ this.warnedInline = true;
328
+ this.logger.warn(`disk "${record.disk}" cannot presign urls: attachments reach the model inline (data: urls, persisted with each message). Use a presign-capable disk or resolveUrl in production.`);
329
+ }
330
+ const bytes = await disk.get(record.path);
331
+ return {
332
+ ...base,
333
+ url: `data:${record.mimeType};base64,${bytes.toString("base64")}`
334
+ };
335
+ }
336
+ };
337
+ function stateOf(record) {
338
+ const state = record.customProperties.agentAttachment;
339
+ return state ?? {
340
+ status: "ready"
341
+ };
342
+ }
343
+ __name(stateOf, "stateOf");
344
+ function safeFileName(filename) {
345
+ const last = filename.split(/[\\/]/).pop() ?? "";
346
+ const cleaned = last.replace(/[\u0000-\u001f\u007f]/g, "").trim();
347
+ return cleaned === "" || cleaned === "." || cleaned === ".." ? "file" : cleaned;
348
+ }
349
+ __name(safeFileName, "safeFileName");
350
+ function stripExtension(fileName) {
351
+ const dot = fileName.lastIndexOf(".");
352
+ return dot > 0 ? fileName.slice(0, dot) : fileName;
353
+ }
354
+ __name(stripExtension, "stripExtension");
355
+
356
+ // src/media/media-attachments.module.ts
357
+ import { AGENT_ATTACHMENT_STAGING, AGENT_STORE } from "@dudousxd/nestjs-agent-core";
358
+ import { MEDIA_STORAGE_SHARED, MEDIA_STORE, MEDIA_UPLOADS } from "@dudousxd/nestjs-media";
359
+ import { Global, Module } from "@nestjs/common";
360
+ import { RouterModule } from "@nestjs/core";
361
+
362
+ // src/media/media-uploads.controller.ts
363
+ import { AGENT_ACTOR_RESOLVER } from "@dudousxd/nestjs-agent-core";
364
+ import { BadRequestException as BadRequestException2, Body, Controller, Delete, HttpCode, Inject, NotFoundException, Param, Post, Req } from "@nestjs/common";
365
+
366
+ // src/media/tokens.ts
367
+ var AGENT_MEDIA_ATTACHMENTS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:media-attachments");
368
+ var AGENT_MEDIA_ATTACHMENTS_OPTIONS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:media-attachments-options");
369
+
370
+ // src/media/media-uploads.controller.ts
371
+ function _ts_decorate(decorators, target, key, desc) {
372
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
373
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
374
+ r = Reflect.decorate(decorators, target, key, desc);
375
+ } else {
376
+ for (var i = decorators.length - 1; i >= 0; i--) {
377
+ if (d = decorators[i]) {
378
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
379
+ }
380
+ }
381
+ }
382
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
383
+ }
384
+ __name(_ts_decorate, "_ts_decorate");
385
+ function _ts_metadata(metadataKey, metadataValue) {
386
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
387
+ return Reflect.metadata(metadataKey, metadataValue);
388
+ }
389
+ }
390
+ __name(_ts_metadata, "_ts_metadata");
391
+ function _ts_param(paramIndex, decorator) {
392
+ return function(target, key) {
393
+ decorator(target, key, paramIndex);
394
+ };
395
+ }
396
+ __name(_ts_param, "_ts_param");
397
+ var AgentMediaUploadsController = class {
398
+ static {
399
+ __name(this, "AgentMediaUploadsController");
400
+ }
401
+ actorResolver;
402
+ staging;
403
+ constructor(actorResolver, staging) {
404
+ this.actorResolver = actorResolver;
405
+ this.staging = staging;
406
+ }
407
+ /** `{ filename, contentType, size }` → `{ mediaId, uploadId, location }`. */
408
+ async begin(req, body) {
409
+ if (typeof body !== "object" || body === null) {
410
+ throw new BadRequestException2("body must be { filename, contentType, size }");
411
+ }
412
+ const { filename, contentType, size } = body;
413
+ const actor = await this.actorResolver.resolve(req);
414
+ return this.staging.beginUpload({
415
+ actor,
416
+ filename,
417
+ contentType,
418
+ size
419
+ });
420
+ }
421
+ async complete(req, mediaId) {
422
+ const actor = await this.actorResolver.resolve(req);
423
+ const attachment = await this.staging.completeUpload({
424
+ actor,
425
+ mediaId
426
+ });
427
+ if (attachment === null) throw new NotFoundException(`attachment ${mediaId} not found`);
428
+ return attachment;
429
+ }
430
+ async discard(req, mediaId) {
431
+ const actor = await this.actorResolver.resolve(req);
432
+ if (!await this.staging.discard({
433
+ actor,
434
+ mediaId
435
+ })) {
436
+ throw new NotFoundException(`attachment ${mediaId} not found`);
437
+ }
438
+ }
439
+ };
440
+ _ts_decorate([
441
+ Post(),
442
+ _ts_param(0, Req()),
443
+ _ts_param(1, Body()),
444
+ _ts_metadata("design:type", Function),
445
+ _ts_metadata("design:paramtypes", [
446
+ typeof Request === "undefined" ? Object : Request,
447
+ Object
448
+ ]),
449
+ _ts_metadata("design:returntype", Promise)
450
+ ], AgentMediaUploadsController.prototype, "begin", null);
451
+ _ts_decorate([
452
+ Post(":mediaId/complete"),
453
+ HttpCode(200),
454
+ _ts_param(0, Req()),
455
+ _ts_param(1, Param("mediaId")),
456
+ _ts_metadata("design:type", Function),
457
+ _ts_metadata("design:paramtypes", [
458
+ typeof Request === "undefined" ? Object : Request,
459
+ String
460
+ ]),
461
+ _ts_metadata("design:returntype", Promise)
462
+ ], AgentMediaUploadsController.prototype, "complete", null);
463
+ _ts_decorate([
464
+ Delete(":mediaId"),
465
+ HttpCode(204),
466
+ _ts_param(0, Req()),
467
+ _ts_param(1, Param("mediaId")),
468
+ _ts_metadata("design:type", Function),
469
+ _ts_metadata("design:paramtypes", [
470
+ typeof Request === "undefined" ? Object : Request,
471
+ String
472
+ ]),
473
+ _ts_metadata("design:returntype", Promise)
474
+ ], AgentMediaUploadsController.prototype, "discard", null);
475
+ AgentMediaUploadsController = _ts_decorate([
476
+ Controller("attachments/uploads"),
477
+ _ts_param(0, Inject(AGENT_ACTOR_RESOLVER)),
478
+ _ts_param(1, Inject(AGENT_MEDIA_ATTACHMENTS)),
479
+ _ts_metadata("design:type", Function),
480
+ _ts_metadata("design:paramtypes", [
481
+ typeof ActorResolver === "undefined" ? Object : ActorResolver,
482
+ typeof MediaAttachmentStaging === "undefined" ? Object : MediaAttachmentStaging
483
+ ])
484
+ ], AgentMediaUploadsController);
485
+
486
+ // src/media/media-attachments.module.ts
487
+ function _ts_decorate2(decorators, target, key, desc) {
488
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
489
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
490
+ r = Reflect.decorate(decorators, target, key, desc);
491
+ } else {
492
+ for (var i = decorators.length - 1; i >= 0; i--) {
493
+ if (d = decorators[i]) {
494
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
495
+ }
496
+ }
497
+ }
498
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
499
+ }
500
+ __name(_ts_decorate2, "_ts_decorate");
501
+ var GUARDS_METADATA = "__guards__";
502
+ function stagingProvider() {
503
+ return {
504
+ provide: AGENT_MEDIA_ATTACHMENTS,
505
+ inject: [
506
+ AGENT_MEDIA_ATTACHMENTS_OPTIONS,
507
+ MEDIA_STORAGE_SHARED,
508
+ MEDIA_STORE,
509
+ MEDIA_UPLOADS,
510
+ {
511
+ token: AGENT_STORE,
512
+ optional: true
513
+ }
514
+ ],
515
+ useFactory: /* @__PURE__ */ __name((options, storage, store, uploads, agentStore) => {
516
+ if (store === null) {
517
+ throw new Error("AgentMediaAttachmentsModule: MediaModule has no `store`. Chat attachments are media records, so configure MediaModule with a MediaStore (e.g. a database adapter).");
518
+ }
519
+ return new MediaAttachmentStaging2({
520
+ storage,
521
+ store,
522
+ uploads,
523
+ ...agentStore !== void 0 ? {
524
+ agentStore
525
+ } : {}
526
+ }, options);
527
+ }, "useFactory")
528
+ };
529
+ }
530
+ __name(stagingProvider, "stagingProvider");
531
+ function build(mount, optionsProvider, imports = []) {
532
+ const routes = mount.routes !== false;
533
+ Reflect.defineMetadata(GUARDS_METADATA, mount.guards ?? [], AgentMediaUploadsController);
534
+ const guards = [
535
+ ...new Set(mount.guards ?? [])
536
+ ];
537
+ return {
538
+ module: AgentMediaAttachmentsModule,
539
+ global: true,
540
+ imports: [
541
+ ...imports,
542
+ ...routes ? [
543
+ RouterModule.register([
544
+ {
545
+ path: mount.path ?? "agent",
546
+ module: AgentMediaAttachmentsModule
547
+ }
548
+ ])
549
+ ] : []
550
+ ],
551
+ controllers: routes ? [
552
+ AgentMediaUploadsController
553
+ ] : [],
554
+ providers: [
555
+ optionsProvider,
556
+ stagingProvider(),
557
+ {
558
+ provide: AGENT_ATTACHMENT_STAGING,
559
+ useExisting: AGENT_MEDIA_ATTACHMENTS
560
+ },
561
+ {
562
+ provide: MediaAttachmentStaging2,
563
+ useExisting: AGENT_MEDIA_ATTACHMENTS
564
+ },
565
+ ...guards
566
+ ],
567
+ exports: [
568
+ AGENT_ATTACHMENT_STAGING,
569
+ AGENT_MEDIA_ATTACHMENTS,
570
+ MediaAttachmentStaging2
571
+ ]
572
+ };
573
+ }
574
+ __name(build, "build");
575
+ var AgentMediaAttachmentsModule = class {
576
+ static {
577
+ __name(this, "AgentMediaAttachmentsModule");
578
+ }
579
+ static forRoot(options = {}) {
580
+ return build(options, {
581
+ provide: AGENT_MEDIA_ATTACHMENTS_OPTIONS,
582
+ useValue: options
583
+ });
584
+ }
585
+ static forRootAsync(options) {
586
+ return build(options, {
587
+ provide: AGENT_MEDIA_ATTACHMENTS_OPTIONS,
588
+ inject: options.inject ?? [],
589
+ useFactory: options.useFactory
590
+ }, options.imports);
591
+ }
592
+ };
593
+ AgentMediaAttachmentsModule = _ts_decorate2([
594
+ Global(),
595
+ Module({})
596
+ ], AgentMediaAttachmentsModule);
597
+ export {
598
+ AGENT_MEDIA_ATTACHMENTS,
599
+ AGENT_MEDIA_ATTACHMENTS_OPTIONS,
600
+ AgentMediaAttachmentsModule,
601
+ AgentMediaUploadsController,
602
+ DEFAULT_AGENT_MEDIA_COLLECTION,
603
+ DEFAULT_AGENT_MEDIA_OWNER_TYPE,
604
+ DEFAULT_AGENT_MEDIA_TUS_BASE_PATH,
605
+ DEFAULT_AGENT_MEDIA_URL_TTL_SECONDS,
606
+ MediaAttachmentStaging2 as MediaAttachmentStaging
607
+ };
608
+ //# sourceMappingURL=index.js.map