@adonis-agora/media 0.1.0 → 0.2.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 (137) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/configure.d.ts +2 -2
  3. package/dist/configure.d.ts.map +1 -1
  4. package/dist/configure.js +3 -2
  5. package/dist/configure.js.map +1 -1
  6. package/dist/providers/media_provider.d.ts +15 -0
  7. package/dist/providers/media_provider.d.ts.map +1 -1
  8. package/dist/providers/media_provider.js +224 -12
  9. package/dist/providers/media_provider.js.map +1 -1
  10. package/dist/src/attachment.d.ts +1 -0
  11. package/dist/src/attachment.d.ts.map +1 -1
  12. package/dist/src/attachment.js +52 -21
  13. package/dist/src/attachment.js.map +1 -1
  14. package/dist/src/define_config.d.ts +83 -5
  15. package/dist/src/define_config.d.ts.map +1 -1
  16. package/dist/src/define_config.js +3 -1
  17. package/dist/src/define_config.js.map +1 -1
  18. package/dist/src/diagnostics.d.ts +32 -1
  19. package/dist/src/diagnostics.d.ts.map +1 -1
  20. package/dist/src/diagnostics.js.map +1 -1
  21. package/dist/src/disks/factory.d.ts +62 -0
  22. package/dist/src/disks/factory.d.ts.map +1 -0
  23. package/dist/src/disks/factory.js +57 -0
  24. package/dist/src/disks/factory.js.map +1 -0
  25. package/dist/src/disks/s3.d.ts +70 -0
  26. package/dist/src/disks/s3.d.ts.map +1 -0
  27. package/dist/src/disks/s3.js +347 -0
  28. package/dist/src/disks/s3.js.map +1 -0
  29. package/dist/src/disks/xml_fallback.d.ts +29 -0
  30. package/dist/src/disks/xml_fallback.d.ts.map +1 -0
  31. package/dist/src/disks/xml_fallback.js +68 -0
  32. package/dist/src/disks/xml_fallback.js.map +1 -0
  33. package/dist/src/errors.d.ts +34 -0
  34. package/dist/src/errors.d.ts.map +1 -1
  35. package/dist/src/errors.js +60 -0
  36. package/dist/src/errors.js.map +1 -1
  37. package/dist/src/extended_disk.d.ts +10 -0
  38. package/dist/src/extended_disk.d.ts.map +1 -0
  39. package/dist/src/extended_disk.js +19 -0
  40. package/dist/src/extended_disk.js.map +1 -0
  41. package/dist/src/index.d.ts +17 -7
  42. package/dist/src/index.d.ts.map +1 -1
  43. package/dist/src/index.js +11 -4
  44. package/dist/src/index.js.map +1 -1
  45. package/dist/src/media_library.d.ts +4 -2
  46. package/dist/src/media_library.d.ts.map +1 -1
  47. package/dist/src/media_library.js +78 -32
  48. package/dist/src/media_library.js.map +1 -1
  49. package/dist/src/media_manager.d.ts +48 -0
  50. package/dist/src/media_manager.d.ts.map +1 -1
  51. package/dist/src/media_manager.js +68 -0
  52. package/dist/src/media_manager.js.map +1 -1
  53. package/dist/src/media_store.d.ts +40 -0
  54. package/dist/src/media_store.d.ts.map +1 -1
  55. package/dist/src/media_store.js +28 -1
  56. package/dist/src/media_store.js.map +1 -1
  57. package/dist/src/multipart.d.ts +10 -0
  58. package/dist/src/multipart.d.ts.map +1 -0
  59. package/dist/src/multipart.js +16 -0
  60. package/dist/src/multipart.js.map +1 -0
  61. package/dist/src/resumable_upload.d.ts +131 -0
  62. package/dist/src/resumable_upload.d.ts.map +1 -0
  63. package/dist/src/resumable_upload.js +177 -0
  64. package/dist/src/resumable_upload.js.map +1 -0
  65. package/dist/src/services/main.d.ts +14 -0
  66. package/dist/src/services/main.d.ts.map +1 -0
  67. package/dist/src/services/main.js +18 -0
  68. package/dist/src/services/main.js.map +1 -0
  69. package/dist/src/stores/factory.d.ts +12 -4
  70. package/dist/src/stores/factory.d.ts.map +1 -1
  71. package/dist/src/stores/factory.js +20 -1
  72. package/dist/src/stores/factory.js.map +1 -1
  73. package/dist/src/stores/lucid.d.ts +2 -1
  74. package/dist/src/stores/lucid.d.ts.map +1 -1
  75. package/dist/src/stores/lucid.js +42 -7
  76. package/dist/src/stores/lucid.js.map +1 -1
  77. package/dist/src/telescope/dashboard.d.ts +19 -0
  78. package/dist/src/telescope/dashboard.d.ts.map +1 -0
  79. package/dist/src/telescope/dashboard.js +116 -0
  80. package/dist/src/telescope/dashboard.js.map +1 -0
  81. package/dist/src/telescope/data-providers.d.ts +36 -0
  82. package/dist/src/telescope/data-providers.d.ts.map +1 -0
  83. package/dist/src/telescope/data-providers.js +286 -0
  84. package/dist/src/telescope/data-providers.js.map +1 -0
  85. package/dist/src/telescope/extension.d.ts +26 -0
  86. package/dist/src/telescope/extension.d.ts.map +1 -0
  87. package/dist/src/telescope/extension.js +42 -0
  88. package/dist/src/telescope/extension.js.map +1 -0
  89. package/dist/src/telescope/index.d.ts +5 -0
  90. package/dist/src/telescope/index.d.ts.map +1 -0
  91. package/dist/src/telescope/index.js +4 -0
  92. package/dist/src/telescope/index.js.map +1 -0
  93. package/dist/src/telescope/telescope-sdk.d.ts +125 -0
  94. package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
  95. package/dist/src/telescope/telescope-sdk.js +14 -0
  96. package/dist/src/telescope/telescope-sdk.js.map +1 -0
  97. package/dist/src/testing/in_memory_disk.d.ts +1 -0
  98. package/dist/src/testing/in_memory_disk.d.ts.map +1 -1
  99. package/dist/src/testing/in_memory_disk.js +10 -0
  100. package/dist/src/testing/in_memory_disk.js.map +1 -1
  101. package/dist/src/testing/in_memory_media_store.d.ts +2 -1
  102. package/dist/src/testing/in_memory_media_store.d.ts.map +1 -1
  103. package/dist/src/testing/in_memory_media_store.js +28 -0
  104. package/dist/src/testing/in_memory_media_store.js.map +1 -1
  105. package/dist/src/testing/in_memory_upload_session_store.d.ts +18 -0
  106. package/dist/src/testing/in_memory_upload_session_store.d.ts.map +1 -0
  107. package/dist/src/testing/in_memory_upload_session_store.js +40 -0
  108. package/dist/src/testing/in_memory_upload_session_store.js.map +1 -0
  109. package/dist/src/testing/index.d.ts +1 -0
  110. package/dist/src/testing/index.d.ts.map +1 -1
  111. package/dist/src/testing/index.js +1 -0
  112. package/dist/src/testing/index.js.map +1 -1
  113. package/dist/src/tus.d.ts +57 -0
  114. package/dist/src/tus.d.ts.map +1 -0
  115. package/dist/src/tus.js +143 -0
  116. package/dist/src/tus.js.map +1 -0
  117. package/dist/src/types.d.ts +118 -0
  118. package/dist/src/types.d.ts.map +1 -1
  119. package/dist/src/upload_manager.d.ts +127 -0
  120. package/dist/src/upload_manager.d.ts.map +1 -0
  121. package/dist/src/upload_manager.js +152 -0
  122. package/dist/src/upload_manager.js.map +1 -0
  123. package/dist/src/upload_mode.d.ts +27 -0
  124. package/dist/src/upload_mode.d.ts.map +1 -0
  125. package/dist/src/upload_mode.js +22 -0
  126. package/dist/src/upload_mode.js.map +1 -0
  127. package/dist/src/upload_sessions/factory.d.ts +62 -0
  128. package/dist/src/upload_sessions/factory.d.ts.map +1 -0
  129. package/dist/src/upload_sessions/factory.js +60 -0
  130. package/dist/src/upload_sessions/factory.js.map +1 -0
  131. package/dist/src/upload_sessions/lucid.d.ts +35 -0
  132. package/dist/src/upload_sessions/lucid.d.ts.map +1 -0
  133. package/dist/src/upload_sessions/lucid.js +105 -0
  134. package/dist/src/upload_sessions/lucid.js.map +1 -0
  135. package/dist/stubs/config/media.stub +16 -1
  136. package/dist/stubs/database/migrations/create_media_upload_sessions_table.stub +45 -0
  137. package/package.json +40 -1
@@ -0,0 +1,35 @@
1
+ import type { Database } from '@adonisjs/lucid/database';
2
+ import type { UploadSession, UploadSessionListFilter, UploadSessionStore } from '../resumable_upload.js';
3
+ import type { MultipartPart } from '../types.js';
4
+ export interface LucidUploadSessionStoreOptions {
5
+ /** Lucid connection name. Defaults to the `Database` default connection. */
6
+ connectionName?: string;
7
+ /** Sessions table name. Default `media_upload_sessions`. */
8
+ table?: string;
9
+ /** Parts side-index table name. Default `media_upload_parts`. */
10
+ partsTable?: string;
11
+ }
12
+ /**
13
+ * Lucid-backed {@link UploadSessionStore}. Persists resumable upload sessions in
14
+ * `media_upload_sessions` and, for multipart-capable disks, the per-part ETags in
15
+ * `media_upload_parts`, via `@adonisjs/lucid`'s query builder (Knex) — so it works across
16
+ * SQLite / Postgres / MySQL. JSON `metadata` is stored as TEXT and timestamps as epoch-ms integers,
17
+ * keeping the schema portable, exactly like {@link LucidMediaStore}. Publish the migration with
18
+ * `node ace configure @adonis-agora/media`.
19
+ */
20
+ export declare class LucidUploadSessionStore implements UploadSessionStore {
21
+ private readonly db;
22
+ private readonly table;
23
+ private readonly partsTable;
24
+ private readonly connectionName;
25
+ constructor(db: Database, options?: LucidUploadSessionStoreOptions);
26
+ private client;
27
+ create(session: UploadSession): Promise<UploadSession>;
28
+ get(id: string): Promise<UploadSession | null>;
29
+ update(session: UploadSession): Promise<UploadSession>;
30
+ delete(id: string): Promise<void>;
31
+ addPart(id: string, part: MultipartPart): Promise<void>;
32
+ listParts(id: string): Promise<MultipartPart[]>;
33
+ list(filter?: UploadSessionListFilter): Promise<UploadSession[]>;
34
+ }
35
+ //# sourceMappingURL=lucid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lucid.d.ts","sourceRoot":"","sources":["../../../src/upload_sessions/lucid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,8BAA8B;IAC7C,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAwBD;;;;;;;GAOG;AACH,qBAAa,uBAAwB,YAAW,kBAAkB;IAM9D,OAAO,CAAC,QAAQ,CAAC,EAAE;IALrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;gBAGjC,EAAE,EAAE,QAAQ,EAC7B,OAAO,GAAE,8BAAmC;IAO9C,OAAO,CAAC,MAAM;IAIR,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAMtD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAK9C,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAKtD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IASvD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAQ/C,IAAI,CAAC,MAAM,GAAE,uBAA4B,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAO3E"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Lucid-backed {@link UploadSessionStore}. Persists resumable upload sessions in
3
+ * `media_upload_sessions` and, for multipart-capable disks, the per-part ETags in
4
+ * `media_upload_parts`, via `@adonisjs/lucid`'s query builder (Knex) — so it works across
5
+ * SQLite / Postgres / MySQL. JSON `metadata` is stored as TEXT and timestamps as epoch-ms integers,
6
+ * keeping the schema portable, exactly like {@link LucidMediaStore}. Publish the migration with
7
+ * `node ace configure @adonis-agora/media`.
8
+ */
9
+ export class LucidUploadSessionStore {
10
+ db;
11
+ table;
12
+ partsTable;
13
+ connectionName;
14
+ constructor(db, options = {}) {
15
+ this.db = db;
16
+ this.table = options.table ?? 'media_upload_sessions';
17
+ this.partsTable = options.partsTable ?? 'media_upload_parts';
18
+ this.connectionName = options.connectionName;
19
+ }
20
+ client() {
21
+ return this.connectionName ? this.db.connection(this.connectionName) : this.db.connection();
22
+ }
23
+ async create(session) {
24
+ const stored = { ...session, createdAt: session.createdAt ?? new Date() };
25
+ await this.client().table(this.table).insert(toRow(stored)).onConflict('id').merge();
26
+ return { ...stored };
27
+ }
28
+ async get(id) {
29
+ const row = (await this.client().from(this.table).where('id', id).first());
30
+ return row ? fromRow(row) : null;
31
+ }
32
+ async update(session) {
33
+ await this.client().table(this.table).insert(toRow(session)).onConflict('id').merge();
34
+ return { ...session };
35
+ }
36
+ async delete(id) {
37
+ await this.client().from(this.table).where('id', id).delete();
38
+ await this.client().from(this.partsTable).where('session_id', id).delete();
39
+ }
40
+ async addPart(id, part) {
41
+ // Upsert by (session_id, part_number) so a retried part overwrites rather than duplicates.
42
+ await this.client()
43
+ .table(this.partsTable)
44
+ .insert({ session_id: id, part_number: part.partNumber, etag: part.etag })
45
+ .onConflict(['session_id', 'part_number'])
46
+ .merge();
47
+ }
48
+ async listParts(id) {
49
+ const rows = (await this.client()
50
+ .from(this.partsTable)
51
+ .where('session_id', id)
52
+ .orderBy('part_number', 'asc'));
53
+ return rows.map((r) => ({ partNumber: Number(r.part_number), etag: r.etag }));
54
+ }
55
+ async list(filter = {}) {
56
+ let q = this.client().from(this.table);
57
+ if (filter.disk !== undefined)
58
+ q = q.where('disk', filter.disk);
59
+ if (filter.keyPrefix !== undefined)
60
+ q = q.where('key', 'like', `${filter.keyPrefix}%`);
61
+ const rows = (await q.orderBy('created_at', 'asc'));
62
+ return rows.map(fromRow);
63
+ }
64
+ }
65
+ function toRow(session) {
66
+ return {
67
+ id: session.id,
68
+ disk: session.disk,
69
+ key: session.key,
70
+ content_type: session.contentType ?? null,
71
+ size: session.size ?? null,
72
+ offset: session.offset,
73
+ parts: session.parts,
74
+ multipart_upload_id: session.multipartUploadId ?? null,
75
+ metadata: session.metadata ? JSON.stringify(session.metadata) : null,
76
+ created_at: (session.createdAt ?? new Date()).getTime(),
77
+ expires_at: session.expiresAt ? session.expiresAt.getTime() : null,
78
+ };
79
+ }
80
+ function fromRow(row) {
81
+ const session = {
82
+ id: row.id,
83
+ disk: row.disk,
84
+ key: row.key,
85
+ contentType: row.content_type ?? undefined,
86
+ size: row.size === null ? undefined : Number(row.size),
87
+ offset: Number(row.offset),
88
+ parts: Number(row.parts),
89
+ createdAt: new Date(Number(row.created_at)),
90
+ };
91
+ if (row.multipart_upload_id)
92
+ session.multipartUploadId = row.multipart_upload_id;
93
+ if (row.expires_at !== null)
94
+ session.expiresAt = new Date(Number(row.expires_at));
95
+ if (row.metadata) {
96
+ try {
97
+ session.metadata = JSON.parse(row.metadata);
98
+ }
99
+ catch {
100
+ // ignore malformed metadata
101
+ }
102
+ }
103
+ return session;
104
+ }
105
+ //# sourceMappingURL=lucid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lucid.js","sourceRoot":"","sources":["../../../src/upload_sessions/lucid.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  {{{
2
2
  exports({ to: app.configPath('media.ts') })
3
3
  }}}
4
- import { defineConfig, stores, processors } from '@adonis-agora/media'
4
+ import { defineConfig, stores, processors, uploadSessions } from '@adonis-agora/media'
5
5
 
6
6
  /**
7
7
  * Configuration for @adonis-agora/media. Storage is delegated to @adonisjs/drive — `disk` names a disk
@@ -33,4 +33,19 @@ export default defineConfig({
33
33
  ],
34
34
  },
35
35
  ],
36
+
37
+ // Resumable (TUS) uploads — opt-in. Mounts the TUS protocol under `routes.prefix` and persists
38
+ // upload sessions so a dropped connection resumes. Select `lucid` and run `node ace migration:run`
39
+ // for durable, multi-process sessions; the default in-memory store is single-process only.
40
+ // uploads: {
41
+ // resumable: {
42
+ // store: 'lucid',
43
+ // stores: {
44
+ // memory: uploadSessions.memory(),
45
+ // lucid: uploadSessions.lucid(),
46
+ // },
47
+ // sessionTtlSeconds: 24 * 60 * 60,
48
+ // routes: { enabled: true, prefix: '/media/uploads/tus' },
49
+ // },
50
+ // },
36
51
  })
@@ -0,0 +1,45 @@
1
+ {{{
2
+ exports({ to: app.migrationsPath(`${new Date().getTime()}_create_media_upload_sessions_table.ts`) })
3
+ }}}
4
+ import { BaseSchema } from '@adonisjs/lucid/schema'
5
+
6
+ /**
7
+ * Tables for the @adonis-agora/media resumable (TUS) `lucid` session store. `media_upload_sessions`
8
+ * persists offset/length/metadata/expiry so a dropped upload resumes; `media_upload_parts` is the
9
+ * per-part ETag side-index used to assemble native S3 multipart uploads. JSON `metadata` is stored as
10
+ * TEXT and timestamps as epoch-ms integers, so the schema is portable across SQLite / Postgres / MySQL.
11
+ * Only needed if you enable `uploads.resumable` with the `lucid` session store.
12
+ */
13
+ export default class extends BaseSchema {
14
+ protected sessionsTable = 'media_upload_sessions'
15
+ protected partsTable = 'media_upload_parts'
16
+
17
+ async up() {
18
+ this.schema.createTable(this.sessionsTable, (table) => {
19
+ table.string('id').primary()
20
+ table.string('disk').notNullable()
21
+ table.text('key').notNullable()
22
+ table.string('content_type').nullable()
23
+ table.bigInteger('size').nullable()
24
+ table.bigInteger('offset').notNullable().defaultTo(0)
25
+ table.integer('parts').notNullable().defaultTo(0)
26
+ table.string('multipart_upload_id').nullable()
27
+ table.text('metadata').nullable()
28
+ table.bigInteger('created_at').notNullable()
29
+ table.bigInteger('expires_at').nullable()
30
+ table.index(['disk'], 'media_upload_sessions_disk_idx')
31
+ })
32
+
33
+ this.schema.createTable(this.partsTable, (table) => {
34
+ table.string('session_id').notNullable()
35
+ table.integer('part_number').notNullable()
36
+ table.string('etag').notNullable()
37
+ table.primary(['session_id', 'part_number'])
38
+ })
39
+ }
40
+
41
+ async down() {
42
+ this.schema.dropTable(this.partsTable)
43
+ this.schema.dropTable(this.sessionsTable)
44
+ }
45
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonis-agora/media",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Media-library for AdonisJS — owner collections (MIME whitelist, single-file replace, ordering), image conversions (eager/lazy), and column attachments, all on top of @adonisjs/drive. Pluggable MediaStore (in-memory + Lucid) and ImageProcessor (sharp). Part of the Agora ecosystem.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -18,6 +18,11 @@
18
18
  "import": "./dist/src/index.js",
19
19
  "default": "./dist/src/index.js"
20
20
  },
21
+ "./services/main": {
22
+ "types": "./dist/src/services/main.d.ts",
23
+ "import": "./dist/src/services/main.js",
24
+ "default": "./dist/src/services/main.js"
25
+ },
21
26
  "./media_provider": {
22
27
  "types": "./dist/providers/media_provider.d.ts",
23
28
  "import": "./dist/providers/media_provider.js",
@@ -33,6 +38,16 @@
33
38
  "import": "./dist/src/stores/lucid.js",
34
39
  "default": "./dist/src/stores/lucid.js"
35
40
  },
41
+ "./upload_sessions/lucid": {
42
+ "types": "./dist/src/upload_sessions/lucid.d.ts",
43
+ "import": "./dist/src/upload_sessions/lucid.js",
44
+ "default": "./dist/src/upload_sessions/lucid.js"
45
+ },
46
+ "./disks/s3": {
47
+ "types": "./dist/src/disks/s3.d.ts",
48
+ "import": "./dist/src/disks/s3.js",
49
+ "default": "./dist/src/disks/s3.js"
50
+ },
36
51
  "./processors/sharp": {
37
52
  "types": "./dist/src/processors/sharp.d.ts",
38
53
  "import": "./dist/src/processors/sharp.js",
@@ -47,6 +62,11 @@
47
62
  "types": "./dist/src/types.d.ts",
48
63
  "import": "./dist/src/types.js",
49
64
  "default": "./dist/src/types.js"
65
+ },
66
+ "./telescope": {
67
+ "types": "./dist/src/telescope/index.d.ts",
68
+ "import": "./dist/src/telescope/index.js",
69
+ "default": "./dist/src/telescope/index.js"
50
70
  }
51
71
  },
52
72
  "files": [
@@ -59,12 +79,24 @@
59
79
  "@adonisjs/core": "^7.3.0",
60
80
  "@adonisjs/drive": "^3.0.0",
61
81
  "@adonisjs/lucid": "^22.4.0",
82
+ "@adonis-agora/telescope": "^0.4.0",
83
+ "@aws-sdk/client-s3": "^3.0.0",
84
+ "@aws-sdk/s3-request-presigner": "^3.0.0",
62
85
  "sharp": "^0.33.0"
63
86
  },
64
87
  "peerDependenciesMeta": {
88
+ "@adonis-agora/telescope": {
89
+ "optional": true
90
+ },
65
91
  "@adonisjs/lucid": {
66
92
  "optional": true
67
93
  },
94
+ "@aws-sdk/client-s3": {
95
+ "optional": true
96
+ },
97
+ "@aws-sdk/s3-request-presigner": {
98
+ "optional": true
99
+ },
68
100
  "sharp": {
69
101
  "optional": true
70
102
  }
@@ -74,7 +106,14 @@
74
106
  "@adonisjs/core": "^7.3.0",
75
107
  "@adonisjs/drive": "^3.0.0",
76
108
  "@adonisjs/lucid": "^22.4.0",
109
+ "@aws-sdk/client-s3": "^3.726.1",
110
+ "@aws-sdk/s3-request-presigner": "^3.726.1",
111
+ "@smithy/util-stream": "^3.3.1",
112
+ "@types/better-sqlite3": "^7.6.0",
77
113
  "@types/node": "^20.0.0",
114
+ "aws-sdk-client-mock": "^4.1.0",
115
+ "better-sqlite3": "^11.0.0",
116
+ "luxon": "^3.4.0",
78
117
  "sharp": "^0.33.0",
79
118
  "typescript": "^5.4.0",
80
119
  "vitest": "^3.0.0"