@adonis-agora/media 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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/dist/configure.d.ts +13 -0
  3. package/dist/configure.d.ts.map +1 -0
  4. package/dist/configure.js +20 -0
  5. package/dist/configure.js.map +1 -0
  6. package/dist/providers/media_provider.d.ts +20 -0
  7. package/dist/providers/media_provider.d.ts.map +1 -0
  8. package/dist/providers/media_provider.js +71 -0
  9. package/dist/providers/media_provider.js.map +1 -0
  10. package/dist/src/attachment.d.ts +83 -0
  11. package/dist/src/attachment.d.ts.map +1 -0
  12. package/dist/src/attachment.js +144 -0
  13. package/dist/src/attachment.js.map +1 -0
  14. package/dist/src/contents.d.ts +9 -0
  15. package/dist/src/contents.d.ts.map +1 -0
  16. package/dist/src/contents.js +17 -0
  17. package/dist/src/contents.js.map +1 -0
  18. package/dist/src/define_config.d.ts +58 -0
  19. package/dist/src/define_config.d.ts.map +1 -0
  20. package/dist/src/define_config.js +8 -0
  21. package/dist/src/define_config.js.map +1 -0
  22. package/dist/src/diagnostics.d.ts +49 -0
  23. package/dist/src/diagnostics.d.ts.map +1 -0
  24. package/dist/src/diagnostics.js +24 -0
  25. package/dist/src/diagnostics.js.map +1 -0
  26. package/dist/src/errors.d.ts +17 -0
  27. package/dist/src/errors.d.ts.map +1 -0
  28. package/dist/src/errors.js +29 -0
  29. package/dist/src/errors.js.map +1 -0
  30. package/dist/src/image_processor.d.ts +21 -0
  31. package/dist/src/image_processor.d.ts.map +1 -0
  32. package/dist/src/image_processor.js +2 -0
  33. package/dist/src/image_processor.js.map +1 -0
  34. package/dist/src/index.d.ts +20 -0
  35. package/dist/src/index.d.ts.map +1 -0
  36. package/dist/src/index.js +13 -0
  37. package/dist/src/index.js.map +1 -0
  38. package/dist/src/media_collection.d.ts +19 -0
  39. package/dist/src/media_collection.d.ts.map +1 -0
  40. package/dist/src/media_collection.js +12 -0
  41. package/dist/src/media_collection.js.map +1 -0
  42. package/dist/src/media_library.d.ts +71 -0
  43. package/dist/src/media_library.d.ts.map +1 -0
  44. package/dist/src/media_library.js +176 -0
  45. package/dist/src/media_library.js.map +1 -0
  46. package/dist/src/media_manager.d.ts +38 -0
  47. package/dist/src/media_manager.d.ts.map +1 -0
  48. package/dist/src/media_manager.js +46 -0
  49. package/dist/src/media_manager.js.map +1 -0
  50. package/dist/src/media_record.d.ts +25 -0
  51. package/dist/src/media_record.d.ts.map +1 -0
  52. package/dist/src/media_record.js +2 -0
  53. package/dist/src/media_record.js.map +1 -0
  54. package/dist/src/media_store.d.ts +16 -0
  55. package/dist/src/media_store.d.ts.map +1 -0
  56. package/dist/src/media_store.js +2 -0
  57. package/dist/src/media_store.js.map +1 -0
  58. package/dist/src/processors/factory.d.ts +22 -0
  59. package/dist/src/processors/factory.d.ts.map +1 -0
  60. package/dist/src/processors/factory.js +21 -0
  61. package/dist/src/processors/factory.js.map +1 -0
  62. package/dist/src/processors/sharp.d.ts +10 -0
  63. package/dist/src/processors/sharp.d.ts.map +1 -0
  64. package/dist/src/processors/sharp.js +29 -0
  65. package/dist/src/processors/sharp.js.map +1 -0
  66. package/dist/src/storage_manager.d.ts +19 -0
  67. package/dist/src/storage_manager.d.ts.map +1 -0
  68. package/dist/src/storage_manager.js +17 -0
  69. package/dist/src/storage_manager.js.map +1 -0
  70. package/dist/src/stores/factory.d.ts +51 -0
  71. package/dist/src/stores/factory.d.ts.map +1 -0
  72. package/dist/src/stores/factory.js +39 -0
  73. package/dist/src/stores/factory.js.map +1 -0
  74. package/dist/src/stores/lucid.d.ts +29 -0
  75. package/dist/src/stores/lucid.d.ts.map +1 -0
  76. package/dist/src/stores/lucid.js +106 -0
  77. package/dist/src/stores/lucid.js.map +1 -0
  78. package/dist/src/testing/fake_image_processor.d.ts +14 -0
  79. package/dist/src/testing/fake_image_processor.d.ts.map +1 -0
  80. package/dist/src/testing/fake_image_processor.js +21 -0
  81. package/dist/src/testing/fake_image_processor.js.map +1 -0
  82. package/dist/src/testing/in_memory_disk.d.ts +44 -0
  83. package/dist/src/testing/in_memory_disk.d.ts.map +1 -0
  84. package/dist/src/testing/in_memory_disk.js +80 -0
  85. package/dist/src/testing/in_memory_disk.js.map +1 -0
  86. package/dist/src/testing/in_memory_media_store.d.ts +12 -0
  87. package/dist/src/testing/in_memory_media_store.d.ts.map +1 -0
  88. package/dist/src/testing/in_memory_media_store.js +29 -0
  89. package/dist/src/testing/in_memory_media_store.js.map +1 -0
  90. package/dist/src/testing/index.d.ts +4 -0
  91. package/dist/src/testing/index.d.ts.map +1 -0
  92. package/dist/src/testing/index.js +4 -0
  93. package/dist/src/testing/index.js.map +1 -0
  94. package/dist/src/types.d.ts +44 -0
  95. package/dist/src/types.d.ts.map +1 -0
  96. package/dist/src/types.js +2 -0
  97. package/dist/src/types.js.map +1 -0
  98. package/dist/stubs/config/media.stub +36 -0
  99. package/dist/stubs/database/migrations/create_media_table.stub +39 -0
  100. package/dist/stubs/main.d.ts +3 -0
  101. package/dist/stubs/main.d.ts.map +1 -0
  102. package/dist/stubs/main.js +4 -0
  103. package/dist/stubs/main.js.map +1 -0
  104. package/package.json +106 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Davi Carvalho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ import type Configure from '@adonisjs/core/commands/configure';
2
+ /**
3
+ * `node ace configure @adonis-agora/media` — auto-wires the package:
4
+ *
5
+ * 1. registers the media service provider in `adonisrc.ts`;
6
+ * 2. publishes `config/media.ts`;
7
+ * 3. publishes the Lucid migration for the optional `lucid` store (run
8
+ * `node ace migration:run`; delete it if you only use the in-memory store).
9
+ *
10
+ * Requires `@adonisjs/drive` to be installed and configured first (`node ace add @adonisjs/drive`).
11
+ */
12
+ export declare function configure(command: Configure): Promise<void>;
13
+ //# sourceMappingURL=configure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../configure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,mCAAmC,CAAC;AAG/D;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,SAAS,iBASjD"}
@@ -0,0 +1,20 @@
1
+ import { stubsRoot } from './stubs/main.js';
2
+ /**
3
+ * `node ace configure @adonis-agora/media` — auto-wires the package:
4
+ *
5
+ * 1. registers the media service provider in `adonisrc.ts`;
6
+ * 2. publishes `config/media.ts`;
7
+ * 3. publishes the Lucid migration for the optional `lucid` store (run
8
+ * `node ace migration:run`; delete it if you only use the in-memory store).
9
+ *
10
+ * Requires `@adonisjs/drive` to be installed and configured first (`node ace add @adonisjs/drive`).
11
+ */
12
+ export async function configure(command) {
13
+ const codemods = await command.createCodemods();
14
+ await codemods.updateRcFile((rcFile) => {
15
+ rcFile.addProvider('@adonis-agora/media/media_provider');
16
+ });
17
+ await codemods.makeUsingStub(stubsRoot, 'config/media.stub', {});
18
+ await codemods.makeUsingStub(stubsRoot, 'database/migrations/create_media_table.stub', {});
19
+ }
20
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../configure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAkB;IAChD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC;IAEhD,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACjE,MAAM,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,6CAA6C,EAAE,EAAE,CAAC,CAAC;AAC7F,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ApplicationService } from '@adonisjs/core/types';
2
+ /**
3
+ * Wires `@adonis-agora/media` into the AdonisJS application: binds a singleton {@link MediaManager}
4
+ * built from `config/media.ts`. Storage is delegated to `@adonisjs/drive` — the manager resolves disks
5
+ * from the booted Drive manager, so this package never reimplements disk drivers. The selected store
6
+ * (`memory` / `lucid`) and image processor (`processors.sharp()`) are built lazily from the config so
7
+ * their peer dependencies (`@adonisjs/lucid`, `sharp`) load only when chosen.
8
+ *
9
+ * ```ts
10
+ * const media = await app.container.make(MediaManager)
11
+ * await media.library.attach({ ownerType: 'Post', ownerId: '1', collection: 'gallery', ... })
12
+ * ```
13
+ */
14
+ export default class MediaProvider {
15
+ #private;
16
+ protected app: ApplicationService;
17
+ constructor(app: ApplicationService);
18
+ register(): void;
19
+ }
20
+ //# sourceMappingURL=media_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media_provider.d.ts","sourceRoot":"","sources":["../../providers/media_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAY/D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;;IACpB,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;CAuDT"}
@@ -0,0 +1,71 @@
1
+ import { MediaManager } from '../src/media_manager.js';
2
+ /**
3
+ * Wires `@adonis-agora/media` into the AdonisJS application: binds a singleton {@link MediaManager}
4
+ * built from `config/media.ts`. Storage is delegated to `@adonisjs/drive` — the manager resolves disks
5
+ * from the booted Drive manager, so this package never reimplements disk drivers. The selected store
6
+ * (`memory` / `lucid`) and image processor (`processors.sharp()`) are built lazily from the config so
7
+ * their peer dependencies (`@adonisjs/lucid`, `sharp`) load only when chosen.
8
+ *
9
+ * ```ts
10
+ * const media = await app.container.make(MediaManager)
11
+ * await media.library.attach({ ownerType: 'Post', ownerId: '1', collection: 'gallery', ... })
12
+ * ```
13
+ */
14
+ export default class MediaProvider {
15
+ app;
16
+ constructor(app) {
17
+ this.app = app;
18
+ }
19
+ register() {
20
+ this.app.container.singleton(MediaManager, async () => {
21
+ const config = this.app.config.get('media', {});
22
+ // Resolve disks from Drive without a hard dependency: import its service lazily. The Drive
23
+ // disk satisfies our structural `Disk` (getBytes/put/getUrl/...); cast via `unknown` because
24
+ // Drive's full surface is wider than the subset we use.
25
+ const drive = (await import('@adonisjs/drive/services/main'))
26
+ .default;
27
+ const resolve = (name) => drive.use(name);
28
+ const ctx = { app: this.app };
29
+ const store = await this.#resolveStore(config, ctx);
30
+ const imageProcessor = await this.#resolveImageProcessor(config);
31
+ const defaultDisk = config.disk ?? (await this.#resolveDefaultDiskName());
32
+ return new MediaManager({
33
+ defaultDisk,
34
+ resolve,
35
+ store,
36
+ ...(imageProcessor !== undefined ? { imageProcessor } : {}),
37
+ ...(config.collections !== undefined ? { collections: config.collections } : {}),
38
+ ...(config.attachmentKeyPrefix !== undefined
39
+ ? { attachmentKeyPrefix: config.attachmentKeyPrefix }
40
+ : {}),
41
+ ...(config.emitDiagnostics !== undefined
42
+ ? { emitDiagnostics: config.emitDiagnostics }
43
+ : {}),
44
+ });
45
+ });
46
+ }
47
+ /** Build the configured store; defaults to the in-memory store when none is selected. */
48
+ async #resolveStore(config, ctx) {
49
+ const name = config.store;
50
+ if (name && config.stores?.[name]) {
51
+ return config.stores[name](ctx);
52
+ }
53
+ const { InMemoryMediaStore } = await import('../src/testing/in_memory_media_store.js');
54
+ return new InMemoryMediaStore();
55
+ }
56
+ /** A config `imageProcessor` may be a ready instance or a lazy factory thunk. */
57
+ async #resolveImageProcessor(config) {
58
+ const ip = config.imageProcessor;
59
+ if (!ip)
60
+ return undefined;
61
+ if (typeof ip === 'function')
62
+ return ip();
63
+ return ip;
64
+ }
65
+ /** When the config doesn't name a disk, fall back to Drive's configured default disk name. */
66
+ async #resolveDefaultDiskName() {
67
+ const driveConfig = this.app.config.get('drive', {});
68
+ return driveConfig.default ?? 'default';
69
+ }
70
+ }
71
+ //# sourceMappingURL=media_provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media_provider.js","sourceRoot":"","sources":["../../providers/media_provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import type { Readable } from 'node:stream';
2
+ import type { ConversionPreset, ImageProcessor } from './image_processor.js';
3
+ import type { StorageManager } from './storage_manager.js';
4
+ export interface AttachmentVariant {
5
+ disk: string;
6
+ path: string;
7
+ size: number;
8
+ mimeType: string;
9
+ }
10
+ /** Plain, JSON-serializable shape stored in a model column. */
11
+ export interface AttachmentData {
12
+ name: string;
13
+ disk: string;
14
+ path: string;
15
+ size: number;
16
+ mimeType: string;
17
+ variants: Record<string, AttachmentVariant>;
18
+ meta: Record<string, unknown>;
19
+ }
20
+ /**
21
+ * A file attached to a model as a column value (adonis-attachment style). Pure value
22
+ * object — it carries disk + path + variant metadata and serializes to JSON. URL
23
+ * resolution and deletion go through {@link AttachmentManager} (which holds the disks).
24
+ */
25
+ export declare class Attachment {
26
+ readonly name: string;
27
+ readonly disk: string;
28
+ readonly path: string;
29
+ readonly size: number;
30
+ readonly mimeType: string;
31
+ readonly variants: Record<string, AttachmentVariant>;
32
+ readonly meta: Record<string, unknown>;
33
+ constructor(data: AttachmentData);
34
+ toJSON(): AttachmentData;
35
+ /** Rebuild from a stored column value; returns null for null/undefined. */
36
+ static fromJSON(json: AttachmentData | null | undefined): Attachment | null;
37
+ }
38
+ export interface CreateAttachmentInput {
39
+ fileName: string;
40
+ mimeType: string;
41
+ contents: Buffer | Readable;
42
+ size?: number;
43
+ }
44
+ export interface CreateAttachmentOptions {
45
+ disk?: string;
46
+ /** Key prefix on the disk. Default `attachments`. */
47
+ keyPrefix?: string;
48
+ /** Image variants to generate eagerly (needs an ImageProcessor). */
49
+ variants?: ConversionPreset[];
50
+ /** Display name override (defaults to the file name). */
51
+ name?: string;
52
+ meta?: Record<string, unknown>;
53
+ }
54
+ export interface AttachmentManagerOptions {
55
+ storage: StorageManager;
56
+ imageProcessor?: ImageProcessor;
57
+ keyPrefix?: string;
58
+ idGenerator?: () => string;
59
+ /** Emit `agora:media:attachment.*` diagnostics events (default true). */
60
+ emitDiagnostics?: boolean;
61
+ }
62
+ /**
63
+ * Creates and resolves {@link Attachment}s — the adonis-attachment-style API.
64
+ * `createFromFile` uploads the bytes (and any variants) and returns a value object
65
+ * you assign to a model column.
66
+ */
67
+ export declare class AttachmentManager {
68
+ private readonly storage;
69
+ private readonly imageProcessor;
70
+ private readonly keyPrefix;
71
+ private readonly newId;
72
+ private readonly emitDiagnostics;
73
+ constructor(options: AttachmentManagerOptions);
74
+ createFromFile(input: CreateAttachmentInput, options?: CreateAttachmentOptions): Promise<Attachment>;
75
+ /** Public URL for the attachment, or a named variant. */
76
+ url(attachment: Attachment, variant?: string): Promise<string>;
77
+ /** Signed, expiring URL (presign-capable disks). */
78
+ signedUrl(attachment: Attachment, expiresIn: string | number, variant?: string): Promise<string>;
79
+ /** Remove the attachment and all its variants from storage. */
80
+ delete(attachment: Attachment): Promise<void>;
81
+ private resolve;
82
+ }
83
+ //# sourceMappingURL=attachment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/attachment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { asBuffer, toBytes } from './contents.js';
3
+ import { publishMedia } from './diagnostics.js';
4
+ /**
5
+ * A file attached to a model as a column value (adonis-attachment style). Pure value
6
+ * object — it carries disk + path + variant metadata and serializes to JSON. URL
7
+ * resolution and deletion go through {@link AttachmentManager} (which holds the disks).
8
+ */
9
+ export class Attachment {
10
+ name;
11
+ disk;
12
+ path;
13
+ size;
14
+ mimeType;
15
+ variants;
16
+ meta;
17
+ constructor(data) {
18
+ this.name = data.name;
19
+ this.disk = data.disk;
20
+ this.path = data.path;
21
+ this.size = data.size;
22
+ this.mimeType = data.mimeType;
23
+ this.variants = data.variants;
24
+ this.meta = data.meta;
25
+ }
26
+ toJSON() {
27
+ return {
28
+ name: this.name,
29
+ disk: this.disk,
30
+ path: this.path,
31
+ size: this.size,
32
+ mimeType: this.mimeType,
33
+ variants: this.variants,
34
+ meta: this.meta,
35
+ };
36
+ }
37
+ /** Rebuild from a stored column value; returns null for null/undefined. */
38
+ static fromJSON(json) {
39
+ return json ? new Attachment(json) : null;
40
+ }
41
+ }
42
+ /**
43
+ * Creates and resolves {@link Attachment}s — the adonis-attachment-style API.
44
+ * `createFromFile` uploads the bytes (and any variants) and returns a value object
45
+ * you assign to a model column.
46
+ */
47
+ export class AttachmentManager {
48
+ storage;
49
+ imageProcessor;
50
+ keyPrefix;
51
+ newId;
52
+ emitDiagnostics;
53
+ constructor(options) {
54
+ this.storage = options.storage;
55
+ this.imageProcessor = options.imageProcessor;
56
+ this.keyPrefix = options.keyPrefix ?? 'attachments';
57
+ this.newId = options.idGenerator ?? (() => randomUUID());
58
+ this.emitDiagnostics = options.emitDiagnostics ?? true;
59
+ }
60
+ async createFromFile(input, options = {}) {
61
+ const disk = options.disk ?? this.storage.defaultDisk;
62
+ const prefix = options.keyPrefix ?? this.keyPrefix;
63
+ const id = this.newId();
64
+ const dir = `${prefix}/${id}`;
65
+ const path = `${dir}/${input.fileName}`;
66
+ const bytes = await toBytes(input.contents);
67
+ await this.storage.disk(disk).put(path, bytes, { contentType: input.mimeType });
68
+ const size = input.size ?? (await this.storage.disk(disk).getMetaData(path)).contentLength;
69
+ const variants = {};
70
+ const presets = options.variants ?? [];
71
+ if (presets.length > 0) {
72
+ if (!this.imageProcessor) {
73
+ throw new Error('AttachmentManager: variants requested but no ImageProcessor was configured');
74
+ }
75
+ const original = asBuffer(await this.storage.disk(disk).getBytes(path));
76
+ for (const preset of presets) {
77
+ const result = await this.imageProcessor.convert(original, preset);
78
+ const variantPath = `${dir}/variants/${preset.name}.${result.format}`;
79
+ await this.storage.disk(disk).put(variantPath, result.data, {
80
+ contentType: result.contentType,
81
+ });
82
+ variants[preset.name] = {
83
+ disk,
84
+ path: variantPath,
85
+ size: result.data.byteLength,
86
+ mimeType: result.contentType,
87
+ };
88
+ }
89
+ }
90
+ const attachment = new Attachment({
91
+ name: options.name ?? input.fileName,
92
+ disk,
93
+ path,
94
+ size,
95
+ mimeType: input.mimeType,
96
+ variants,
97
+ meta: options.meta ?? {},
98
+ });
99
+ if (this.emitDiagnostics) {
100
+ publishMedia('attachment.create', {
101
+ disk,
102
+ path,
103
+ size,
104
+ mimeType: attachment.mimeType,
105
+ name: attachment.name,
106
+ variants: Object.keys(variants),
107
+ });
108
+ }
109
+ return attachment;
110
+ }
111
+ /** Public URL for the attachment, or a named variant. */
112
+ async url(attachment, variant) {
113
+ const target = this.resolve(attachment, variant);
114
+ return this.storage.disk(target.disk).getUrl(target.path);
115
+ }
116
+ /** Signed, expiring URL (presign-capable disks). */
117
+ async signedUrl(attachment, expiresIn, variant) {
118
+ const target = this.resolve(attachment, variant);
119
+ return this.storage.disk(target.disk).getSignedUrl(target.path, { expiresIn });
120
+ }
121
+ /** Remove the attachment and all its variants from storage. */
122
+ async delete(attachment) {
123
+ await this.storage.disk(attachment.disk).delete(attachment.path);
124
+ for (const variant of Object.values(attachment.variants)) {
125
+ await this.storage.disk(variant.disk).delete(variant.path);
126
+ }
127
+ if (this.emitDiagnostics) {
128
+ publishMedia('attachment.delete', {
129
+ disk: attachment.disk,
130
+ path: attachment.path,
131
+ variants: Object.keys(attachment.variants),
132
+ });
133
+ }
134
+ }
135
+ resolve(attachment, variant) {
136
+ if (!variant)
137
+ return { disk: attachment.disk, path: attachment.path };
138
+ const v = attachment.variants[variant];
139
+ if (!v)
140
+ throw new Error(`Attachment has no variant "${variant}"`);
141
+ return { disk: v.disk, path: v.path };
142
+ }
143
+ }
144
+ //# sourceMappingURL=attachment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../src/attachment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Readable } from 'node:stream';
2
+ /**
3
+ * Coerce attach/create inputs (a `Buffer` or a `Readable`) to a `Uint8Array` for the disk's `put`,
4
+ * which (matching flydrive) does not accept a stream. A `Buffer` is already a `Uint8Array`.
5
+ */
6
+ export declare function toBytes(contents: Buffer | Readable): Promise<Uint8Array>;
7
+ /** Read back disk bytes as a Node `Buffer` for the image processor (which works on Buffers). */
8
+ export declare function asBuffer(bytes: Uint8Array): Buffer;
9
+ //# sourceMappingURL=contents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contents.d.ts","sourceRoot":"","sources":["../../src/contents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;GAGG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAK9E;AAED,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAElD"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Coerce attach/create inputs (a `Buffer` or a `Readable`) to a `Uint8Array` for the disk's `put`,
3
+ * which (matching flydrive) does not accept a stream. A `Buffer` is already a `Uint8Array`.
4
+ */
5
+ export async function toBytes(contents) {
6
+ if (Buffer.isBuffer(contents))
7
+ return contents;
8
+ const chunks = [];
9
+ for await (const chunk of contents)
10
+ chunks.push(Buffer.from(chunk));
11
+ return Buffer.concat(chunks);
12
+ }
13
+ /** Read back disk bytes as a Node `Buffer` for the image processor (which works on Buffers). */
14
+ export function asBuffer(bytes) {
15
+ return Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
16
+ }
17
+ //# sourceMappingURL=contents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contents.js","sourceRoot":"","sources":["../../src/contents.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAA2B;IACvD,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,QAAQ,CAAC,KAAiB;IACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,58 @@
1
+ import type { ImageProcessor } from './image_processor.js';
2
+ import type { MediaCollectionConfig } from './media_collection.js';
3
+ import { processors } from './processors/factory.js';
4
+ import type { ImageProcessorFactory } from './processors/factory.js';
5
+ import { stores } from './stores/factory.js';
6
+ import type { LucidStoreConfig, MemoryStoreConfig, StoreContext, StoreFactory } from './stores/factory.js';
7
+ /**
8
+ * Shape of `config/media.ts`. Storage is delegated to `@adonisjs/drive` — the `disk` is the name of a
9
+ * disk in your `config/drive.ts`; omit it to use Drive's default disk. Pick a `store` by name from the
10
+ * `stores` map (built with the {@link stores} factory so each peer is imported lazily). Conversions need
11
+ * an `imageProcessor` (use `processors.sharp()` for the optional sharp peer, or pass your own instance).
12
+ *
13
+ * ```ts
14
+ * import { defineConfig, stores, processors } from '@adonis-agora/media'
15
+ *
16
+ * export default defineConfig({
17
+ * disk: 's3',
18
+ * store: 'lucid',
19
+ * stores: {
20
+ * memory: stores.memory(),
21
+ * lucid: stores.lucid({ connection: 'pg' }),
22
+ * },
23
+ * imageProcessor: processors.sharp(),
24
+ * collections: [
25
+ * { name: 'avatar', single: true, acceptsMimeTypes: ['image/png', 'image/jpeg'] },
26
+ * { name: 'gallery', conversions: [{ name: 'thumb', width: 200 }, { name: 'og', width: 1200, eager: true }] },
27
+ * ],
28
+ * })
29
+ * ```
30
+ */
31
+ export interface MediaConfig {
32
+ /**
33
+ * Name of the `@adonisjs/drive` disk media is written to. Omit to use Drive's default disk. A
34
+ * collection may override it per-collection, and each `attach` call may override it per-call.
35
+ */
36
+ disk?: string;
37
+ /** Name of the media store (a key of {@link stores}). Defaults to `memory` (single-process). */
38
+ store?: string;
39
+ /** Named media stores, built with the {@link stores} factory. */
40
+ stores?: Record<string, StoreFactory>;
41
+ /**
42
+ * The image conversion engine. Either a ready {@link ImageProcessor} instance or an
43
+ * {@link ImageProcessorFactory} built with the {@link processors} factory (e.g. `processors.sharp()`)
44
+ * so the heavy peer is imported lazily. Required only if any collection defines conversions.
45
+ */
46
+ imageProcessor?: ImageProcessor | ImageProcessorFactory;
47
+ /** Collection definitions (MIME whitelist, single-file replace, conversions). */
48
+ collections?: MediaCollectionConfig[];
49
+ /** Key prefix for column attachments created via the `AttachmentManager`. Default `attachments`. */
50
+ attachmentKeyPrefix?: string;
51
+ /** Emit `agora:media:*` diagnostics events (default true). */
52
+ emitDiagnostics?: boolean;
53
+ }
54
+ /** Identity helper giving `config/media.ts` full type-checking. */
55
+ export declare function defineConfig(config?: MediaConfig): MediaConfig;
56
+ export { stores, processors };
57
+ export type { StoreContext, StoreFactory, LucidStoreConfig, MemoryStoreConfig, ImageProcessorFactory, };
58
+ //# sourceMappingURL=define_config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../src/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACb,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtC;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,GAAG,qBAAqB,CAAC;IACxD,iFAAiF;IACjF,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACtC,oGAAoG;IACpG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,MAAM,GAAE,WAAgB,GAAG,WAAW,CAElE;AAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAC9B,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,GACtB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { processors } from './processors/factory.js';
2
+ import { stores } from './stores/factory.js';
3
+ /** Identity helper giving `config/media.ts` full type-checking. */
4
+ export function defineConfig(config = {}) {
5
+ return config;
6
+ }
7
+ export { stores, processors };
8
+ //# sourceMappingURL=define_config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../src/define_config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAwD7C,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAC,SAAsB,EAAE;IACnD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,49 @@
1
+ export type MediaDiagnosticEvent = 'attach' | 'delete' | 'conversion' | 'attachment.create' | 'attachment.delete';
2
+ export interface AttachPayload {
3
+ id: string;
4
+ ownerType: string;
5
+ ownerId: string;
6
+ collection: string;
7
+ disk: string;
8
+ path: string;
9
+ size: number;
10
+ mimeType: string;
11
+ }
12
+ export interface DeletePayload {
13
+ id: string;
14
+ ownerType: string;
15
+ ownerId: string;
16
+ }
17
+ export interface ConversionPayload {
18
+ id: string;
19
+ conversion: string;
20
+ path: string;
21
+ }
22
+ export interface AttachmentCreatePayload {
23
+ disk: string;
24
+ path: string;
25
+ size: number;
26
+ mimeType: string;
27
+ name: string;
28
+ variants: string[];
29
+ }
30
+ export interface AttachmentDeletePayload {
31
+ disk: string;
32
+ path: string;
33
+ variants: string[];
34
+ }
35
+ /** Maps each event to its payload type, so {@link publishMedia} is checked at the call site. */
36
+ export interface MediaDiagnosticPayloads {
37
+ attach: AttachPayload;
38
+ delete: DeletePayload;
39
+ conversion: ConversionPayload;
40
+ 'attachment.create': AttachmentCreatePayload;
41
+ 'attachment.delete': AttachmentDeletePayload;
42
+ }
43
+ /**
44
+ * Publish a media event on `agora:media:<event>` via the structural diagnostics slot.
45
+ * No-op when diagnostics isn't installed (the slot is empty) — and it never throws back
46
+ * into the library.
47
+ */
48
+ export declare function publishMedia<E extends MediaDiagnosticEvent>(event: E, payload: MediaDiagnosticPayloads[E]): void;
49
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/diagnostics.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,mBAAmB,GACnB,mBAAmB,CAAC;AAExB,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AACD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,gGAAgG;AAChG,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,mBAAmB,EAAE,uBAAuB,CAAC;IAC7C,mBAAmB,EAAE,uBAAuB,CAAC;CAC9C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,oBAAoB,EACzD,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAClC,IAAI,CASN"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The `@adonis-agora/diagnostics` emit capability, published on this global slot at that
3
+ * package's module load. `@adonis-agora/media` reads it STRUCTURALLY — it never imports or
4
+ * depends on the diagnostics package. When diagnostics isn't installed the slot is empty
5
+ * and emitting is an inert no-op.
6
+ */
7
+ const EMIT_SLOT = Symbol.for('@agora/diagnostics:emit');
8
+ /**
9
+ * Publish a media event on `agora:media:<event>` via the structural diagnostics slot.
10
+ * No-op when diagnostics isn't installed (the slot is empty) — and it never throws back
11
+ * into the library.
12
+ */
13
+ export function publishMedia(event, payload) {
14
+ const emit = globalThis[EMIT_SLOT];
15
+ if (typeof emit === 'function') {
16
+ try {
17
+ emit('media', event, payload);
18
+ }
19
+ catch {
20
+ // diagnostics must never break a media operation
21
+ }
22
+ }
23
+ }
24
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAqDxD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAQ,EACR,OAAmC;IAEnC,MAAM,IAAI,GAAI,UAAsC,CAAC,SAAS,CAAuB,CAAC;IACtF,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export declare class MimeNotAllowedError extends Error {
2
+ readonly code = "E_MEDIA_MIME_NOT_ALLOWED";
3
+ constructor(collection: string, mimeType: string);
4
+ }
5
+ export declare class MediaNotFoundError extends Error {
6
+ readonly code = "E_MEDIA_RECORD_NOT_FOUND";
7
+ constructor(id: string);
8
+ }
9
+ export declare class ConversionNotDefinedError extends Error {
10
+ readonly code = "E_MEDIA_CONVERSION_NOT_DEFINED";
11
+ constructor(collection: string, conversion: string);
12
+ }
13
+ export declare class ImageProcessorMissingError extends Error {
14
+ readonly code = "E_MEDIA_IMAGE_PROCESSOR_MISSING";
15
+ constructor();
16
+ }
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,8BAA8B;gBAC/B,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAIjD;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,8BAA8B;gBAC/B,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,oCAAoC;gBACrC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAInD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,qCAAqC;;CAKnD"}