@jrmc/adonis-attachment 6.0.0-alpha.0 → 6.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/make/attachment_v5_migration.d.ts.map +1 -1
- package/build/commands/make/attachment_v5_migration.js +6 -3
- package/build/commands/make/attachment_v5_migration.js.map +1 -1
- package/build/commands/make/attachments_table.d.ts.map +1 -1
- package/build/commands/make/attachments_table.js +8 -2
- package/build/commands/make/attachments_table.js.map +1 -1
- package/build/index.d.ts +23 -22
- package/build/index.d.ts.map +1 -1
- package/build/index.js +15 -14
- package/build/index.js.map +1 -1
- package/build/providers/attachment_provider.d.ts.map +1 -1
- package/build/providers/attachment_provider.js +16 -0
- package/build/providers/attachment_provider.js.map +1 -1
- package/build/src/core/attachment.d.ts +37 -2
- package/build/src/core/attachment.d.ts.map +1 -1
- package/build/src/core/attachment.js +108 -5
- package/build/src/core/attachment.js.map +1 -1
- package/build/src/core/attachment_options.d.ts +32 -0
- package/build/src/core/attachment_options.d.ts.map +1 -0
- package/build/src/core/attachment_options.js +24 -0
- package/build/src/core/attachment_options.js.map +1 -0
- package/build/src/core/attachment_service.d.ts +7 -1
- package/build/src/core/attachment_service.d.ts.map +1 -1
- package/build/src/core/attachment_service.js +50 -4
- package/build/src/core/attachment_service.js.map +1 -1
- package/build/src/core/index.d.ts +2 -1
- package/build/src/core/index.d.ts.map +1 -1
- package/build/src/core/index.js +2 -1
- package/build/src/core/index.js.map +1 -1
- package/build/src/define_config.d.ts +17 -0
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js +9 -0
- package/build/src/define_config.js.map +1 -1
- package/build/src/integrations/lucid/column/attachment_column.d.ts +18 -0
- package/build/src/integrations/lucid/column/attachment_column.d.ts.map +1 -0
- package/build/src/integrations/lucid/{attachment_column.js → column/attachment_column.js} +26 -13
- package/build/src/integrations/lucid/column/attachment_column.js.map +1 -0
- package/build/src/integrations/lucid/index.d.ts +16 -12
- package/build/src/integrations/lucid/index.d.ts.map +1 -1
- package/build/src/integrations/lucid/index.js +16 -12
- package/build/src/integrations/lucid/index.js.map +1 -1
- package/build/src/integrations/lucid/migrations/legacy/legacy_attachment_migration_stub.d.ts +20 -0
- package/build/src/integrations/lucid/migrations/legacy/legacy_attachment_migration_stub.d.ts.map +1 -0
- package/build/src/integrations/lucid/migrations/legacy/legacy_attachment_migration_stub.js +18 -0
- package/build/src/integrations/lucid/migrations/legacy/legacy_attachment_migration_stub.js.map +1 -0
- package/build/src/integrations/lucid/{migrate_legacy_attachment.d.ts → migrations/legacy/migrate_legacy_attachment.d.ts} +25 -9
- package/build/src/integrations/lucid/migrations/legacy/migrate_legacy_attachment.d.ts.map +1 -0
- package/build/src/integrations/lucid/migrations/legacy/migrate_legacy_attachment.js +94 -0
- package/build/src/integrations/lucid/migrations/legacy/migrate_legacy_attachment.js.map +1 -0
- package/build/src/integrations/lucid/{migrate_legacy_attachment_records.d.ts → migrations/legacy/migrate_legacy_attachment_records.d.ts} +3 -3
- package/build/src/integrations/lucid/migrations/legacy/migrate_legacy_attachment_records.d.ts.map +1 -0
- package/build/src/integrations/lucid/{migrate_legacy_attachment_records.js → migrations/legacy/migrate_legacy_attachment_records.js} +7 -6
- package/build/src/integrations/lucid/migrations/legacy/migrate_legacy_attachment_records.js.map +1 -0
- package/build/src/integrations/lucid/models/attachment_link_model.d.ts +30 -0
- package/build/src/integrations/lucid/models/attachment_link_model.d.ts.map +1 -0
- package/build/src/integrations/lucid/models/attachment_link_model.js +58 -0
- package/build/src/integrations/lucid/models/attachment_link_model.js.map +1 -0
- package/build/src/integrations/lucid/{attachment_model.d.ts → models/attachment_model.d.ts} +2 -6
- package/build/src/integrations/lucid/models/attachment_model.d.ts.map +1 -0
- package/build/src/integrations/lucid/{attachment_model.js → models/attachment_model.js} +1 -13
- package/build/src/integrations/lucid/models/attachment_model.js.map +1 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_lifecycle_service.d.ts +34 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_lifecycle_service.d.ts.map +1 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_lifecycle_service.js +195 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_lifecycle_service.js.map +1 -0
- package/build/src/integrations/lucid/{lucid_attachment_repository.d.ts → persistence/lucid_attachment_repository.d.ts} +3 -3
- package/build/src/integrations/lucid/persistence/lucid_attachment_repository.d.ts.map +1 -0
- package/build/src/integrations/lucid/{lucid_attachment_repository.js → persistence/lucid_attachment_repository.js} +1 -1
- package/build/src/integrations/lucid/persistence/lucid_attachment_repository.js.map +1 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_store.d.ts +48 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_store.d.ts.map +1 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_store.js +224 -0
- package/build/src/integrations/lucid/persistence/lucid_attachment_store.js.map +1 -0
- package/build/src/integrations/lucid/{lucid_variant_generation_service.d.ts → persistence/lucid_variant_generation_service.d.ts} +3 -3
- package/build/src/integrations/lucid/persistence/lucid_variant_generation_service.d.ts.map +1 -0
- package/build/src/integrations/lucid/persistence/lucid_variant_generation_service.js.map +1 -0
- package/build/src/integrations/lucid/{attachment_owner.d.ts → relations/attachment_owner.d.ts} +2 -1
- package/build/src/integrations/lucid/relations/attachment_owner.d.ts.map +1 -0
- package/build/src/integrations/lucid/relations/attachment_owner.js.map +1 -0
- package/build/src/integrations/lucid/relations/attachment_relation.d.ts +71 -0
- package/build/src/integrations/lucid/relations/attachment_relation.d.ts.map +1 -0
- package/build/src/integrations/lucid/relations/attachment_relation.js +266 -0
- package/build/src/integrations/lucid/relations/attachment_relation.js.map +1 -0
- package/build/src/integrations/lucid/schema/attachment_schema_service.d.ts +24 -0
- package/build/src/integrations/lucid/schema/attachment_schema_service.d.ts.map +1 -0
- package/build/src/integrations/lucid/schema/attachment_schema_service.js +68 -0
- package/build/src/integrations/lucid/schema/attachment_schema_service.js.map +1 -0
- package/build/src/integrations/lucid/schema/attachment_table_names.d.ts +15 -0
- package/build/src/integrations/lucid/schema/attachment_table_names.d.ts.map +1 -0
- package/build/src/integrations/lucid/schema/attachment_table_names.js +20 -0
- package/build/src/integrations/lucid/schema/attachment_table_names.js.map +1 -0
- package/build/src/integrations/lucid/schema/attachments_table_stub.d.ts.map +1 -0
- package/build/src/integrations/lucid/{attachments_table_stub.js → schema/attachments_table_stub.js} +2 -4
- package/build/src/integrations/lucid/schema/attachments_table_stub.js.map +1 -0
- package/build/src/integrations/lucid/schema/configure_lucid_attachment_tables.d.ts +12 -0
- package/build/src/integrations/lucid/schema/configure_lucid_attachment_tables.d.ts.map +1 -0
- package/build/src/integrations/lucid/schema/configure_lucid_attachment_tables.js +19 -0
- package/build/src/integrations/lucid/schema/configure_lucid_attachment_tables.js.map +1 -0
- package/build/src/sources/attachment_manager.d.ts +14 -12
- package/build/src/sources/attachment_manager.d.ts.map +1 -1
- package/build/src/sources/attachment_manager.js +14 -6
- package/build/src/sources/attachment_manager.js.map +1 -1
- package/build/stubs/migrations/attachments_table.stub +7 -24
- package/build/{src/integrations/lucid/render_legacy_attachment_migration_script.js → stubs/migrations/legacy_attachment_migration.stub} +13 -15
- package/build/tests/attachment_manager.spec.js +21 -18
- package/build/tests/attachment_manager.spec.js.map +1 -1
- package/build/tests/attachment_manager_service.spec.js +2 -2
- package/build/tests/attachment_manager_service.spec.js.map +1 -1
- package/build/tests/attachment_options.spec.d.ts +2 -0
- package/build/tests/attachment_options.spec.d.ts.map +1 -0
- package/build/tests/attachment_options.spec.js +31 -0
- package/build/tests/attachment_options.spec.js.map +1 -0
- package/build/tests/attachment_provider.spec.js +30 -1
- package/build/tests/attachment_provider.spec.js.map +1 -1
- package/build/tests/{create_legacy_attachment_migration_script.spec.d.ts → attachment_schema_service.spec.d.ts} +1 -1
- package/build/tests/attachment_schema_service.spec.d.ts.map +1 -0
- package/build/tests/attachment_schema_service.spec.js +38 -0
- package/build/tests/attachment_schema_service.spec.js.map +1 -0
- package/build/tests/attachment_service.spec.js +55 -0
- package/build/tests/attachment_service.spec.js.map +1 -1
- package/build/tests/attachment_table_names.spec.d.ts +8 -0
- package/build/tests/attachment_table_names.spec.d.ts.map +1 -0
- package/build/tests/attachment_table_names.spec.js +36 -0
- package/build/tests/attachment_table_names.spec.js.map +1 -0
- package/build/tests/attachments_table_stub.spec.js +41 -5
- package/build/tests/attachments_table_stub.spec.js.map +1 -1
- package/build/tests/define_config.spec.js +34 -0
- package/build/tests/define_config.spec.js.map +1 -1
- package/build/tests/helpers/lucid_test_database.d.ts.map +1 -1
- package/build/tests/helpers/lucid_test_database.js +16 -6
- package/build/tests/helpers/lucid_test_database.js.map +1 -1
- package/build/tests/legacy_attachment_migration_stub.spec.d.ts +8 -0
- package/build/tests/legacy_attachment_migration_stub.spec.d.ts.map +1 -0
- package/build/tests/legacy_attachment_migration_stub.spec.js +57 -0
- package/build/tests/legacy_attachment_migration_stub.spec.js.map +1 -0
- package/build/tests/lucid_attachment_collection_store.spec.d.ts +2 -0
- package/build/tests/lucid_attachment_collection_store.spec.d.ts.map +1 -0
- package/build/tests/lucid_attachment_collection_store.spec.js +53 -0
- package/build/tests/lucid_attachment_collection_store.spec.js.map +1 -0
- package/build/tests/lucid_attachment_column.spec.js +57 -1
- package/build/tests/lucid_attachment_column.spec.js.map +1 -1
- package/build/tests/lucid_attachment_lifecycle_service.spec.js +117 -111
- package/build/tests/lucid_attachment_lifecycle_service.spec.js.map +1 -1
- package/build/tests/lucid_attachment_relation.spec.d.ts +8 -0
- package/build/tests/lucid_attachment_relation.spec.d.ts.map +1 -0
- package/build/tests/lucid_attachment_relation.spec.js +295 -0
- package/build/tests/lucid_attachment_relation.spec.js.map +1 -0
- package/build/tests/lucid_attachment_repository.spec.js +1 -1
- package/build/tests/lucid_attachment_repository.spec.js.map +1 -1
- package/build/tests/lucid_attachment_store.spec.js +24 -50
- package/build/tests/lucid_attachment_store.spec.js.map +1 -1
- package/build/tests/lucid_sqlite_integration.spec.js +23 -18
- package/build/tests/lucid_sqlite_integration.spec.js.map +1 -1
- package/build/tests/lucid_variant_generation_service.spec.js +1 -1
- package/build/tests/lucid_variant_generation_service.spec.js.map +1 -1
- package/build/tests/migrate_legacy_attachment.spec.js +114 -67
- package/build/tests/migrate_legacy_attachment.spec.js.map +1 -1
- package/build/tests/migrate_legacy_attachment_records.spec.js +4 -3
- package/build/tests/migrate_legacy_attachment_records.spec.js.map +1 -1
- package/package.json +4 -2
- package/build/src/integrations/lucid/attachment_column.d.ts +0 -11
- package/build/src/integrations/lucid/attachment_column.d.ts.map +0 -1
- package/build/src/integrations/lucid/attachment_column.js.map +0 -1
- package/build/src/integrations/lucid/attachment_model.d.ts.map +0 -1
- package/build/src/integrations/lucid/attachment_model.js.map +0 -1
- package/build/src/integrations/lucid/attachment_owner.d.ts.map +0 -1
- package/build/src/integrations/lucid/attachment_owner.js.map +0 -1
- package/build/src/integrations/lucid/attachments_table_stub.d.ts.map +0 -1
- package/build/src/integrations/lucid/attachments_table_stub.js.map +0 -1
- package/build/src/integrations/lucid/create_legacy_attachment_migration_script.d.ts +0 -13
- package/build/src/integrations/lucid/create_legacy_attachment_migration_script.d.ts.map +0 -1
- package/build/src/integrations/lucid/create_legacy_attachment_migration_script.js +0 -20
- package/build/src/integrations/lucid/create_legacy_attachment_migration_script.js.map +0 -1
- package/build/src/integrations/lucid/lucid_attachment_lifecycle_service.d.ts +0 -21
- package/build/src/integrations/lucid/lucid_attachment_lifecycle_service.d.ts.map +0 -1
- package/build/src/integrations/lucid/lucid_attachment_lifecycle_service.js +0 -68
- package/build/src/integrations/lucid/lucid_attachment_lifecycle_service.js.map +0 -1
- package/build/src/integrations/lucid/lucid_attachment_repository.d.ts.map +0 -1
- package/build/src/integrations/lucid/lucid_attachment_repository.js.map +0 -1
- package/build/src/integrations/lucid/lucid_attachment_store.d.ts +0 -27
- package/build/src/integrations/lucid/lucid_attachment_store.d.ts.map +0 -1
- package/build/src/integrations/lucid/lucid_attachment_store.js +0 -84
- package/build/src/integrations/lucid/lucid_attachment_store.js.map +0 -1
- package/build/src/integrations/lucid/lucid_variant_generation_service.d.ts.map +0 -1
- package/build/src/integrations/lucid/lucid_variant_generation_service.js.map +0 -1
- package/build/src/integrations/lucid/migrate_legacy_attachment.d.ts.map +0 -1
- package/build/src/integrations/lucid/migrate_legacy_attachment.js +0 -67
- package/build/src/integrations/lucid/migrate_legacy_attachment.js.map +0 -1
- package/build/src/integrations/lucid/migrate_legacy_attachment_records.d.ts.map +0 -1
- package/build/src/integrations/lucid/migrate_legacy_attachment_records.js.map +0 -1
- package/build/src/integrations/lucid/render_legacy_attachment_migration_script.d.ts +0 -11
- package/build/src/integrations/lucid/render_legacy_attachment_migration_script.d.ts.map +0 -1
- package/build/src/integrations/lucid/render_legacy_attachment_migration_script.js.map +0 -1
- package/build/tests/create_legacy_attachment_migration_script.spec.d.ts.map +0 -1
- package/build/tests/create_legacy_attachment_migration_script.spec.js +0 -31
- package/build/tests/create_legacy_attachment_migration_script.spec.js.map +0 -1
- /package/build/src/integrations/lucid/{lucid_variant_generation_service.js → persistence/lucid_variant_generation_service.js} +0 -0
- /package/build/src/integrations/lucid/{attachment_owner.js → relations/attachment_owner.js} +0 -0
- /package/build/src/integrations/lucid/{attachments_table_stub.d.ts → schema/attachments_table_stub.d.ts} +0 -0
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
6
|
*/
|
|
7
7
|
import { test } from '@japa/runner';
|
|
8
|
-
import {
|
|
8
|
+
import { AttachmentService } from '../src/core/attachment_service.js';
|
|
9
|
+
import { LucidAttachmentLifecycleService } from '../src/integrations/lucid/persistence/lucid_attachment_lifecycle_service.js';
|
|
9
10
|
const attachment = {
|
|
10
11
|
id: 'attachment-id',
|
|
11
12
|
disk: 'public',
|
|
@@ -16,45 +17,89 @@ const attachment = {
|
|
|
16
17
|
extname: 'jpg',
|
|
17
18
|
size: 42,
|
|
18
19
|
};
|
|
19
|
-
function
|
|
20
|
+
function makeBlob(value) {
|
|
21
|
+
return {
|
|
22
|
+
id: value.id,
|
|
23
|
+
toAttachment() {
|
|
24
|
+
return value;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function makeLink(value, id = `link-${value.id}`) {
|
|
29
|
+
const blob = makeBlob(value);
|
|
20
30
|
return {
|
|
21
31
|
id,
|
|
32
|
+
attachmentId: value.id,
|
|
33
|
+
attachment: blob,
|
|
22
34
|
toAttachment() {
|
|
23
35
|
return value;
|
|
24
36
|
},
|
|
25
37
|
};
|
|
26
38
|
}
|
|
39
|
+
function makeStore(overrides = {}) {
|
|
40
|
+
const link = makeLink(attachment);
|
|
41
|
+
return {
|
|
42
|
+
async createOriginal() {
|
|
43
|
+
return link;
|
|
44
|
+
},
|
|
45
|
+
async findOriginal() {
|
|
46
|
+
return null;
|
|
47
|
+
},
|
|
48
|
+
async listVariants() {
|
|
49
|
+
return [];
|
|
50
|
+
},
|
|
51
|
+
async releaseOwner() { },
|
|
52
|
+
async restoreOwner() { },
|
|
53
|
+
async remove() {
|
|
54
|
+
return [];
|
|
55
|
+
},
|
|
56
|
+
async createCollectionItem() {
|
|
57
|
+
return link;
|
|
58
|
+
},
|
|
59
|
+
async findCollectionItem() {
|
|
60
|
+
return null;
|
|
61
|
+
},
|
|
62
|
+
async listCollection() {
|
|
63
|
+
return [];
|
|
64
|
+
},
|
|
65
|
+
async moveCollectionItem() {
|
|
66
|
+
return [];
|
|
67
|
+
},
|
|
68
|
+
async removeCollectionItem() {
|
|
69
|
+
return [];
|
|
70
|
+
},
|
|
71
|
+
...overrides,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
27
74
|
test.group('LucidAttachmentLifecycleService', () => {
|
|
28
|
-
test('persists
|
|
75
|
+
test('persists a manager draft before creating its polymorphic link', async ({ assert }) => {
|
|
29
76
|
const events = [];
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
77
|
+
const attachments = new AttachmentService({
|
|
78
|
+
defaultDisk: 'fs',
|
|
79
|
+
createId: () => attachment.id,
|
|
80
|
+
queue: { async enqueue() { } },
|
|
81
|
+
storage: {
|
|
82
|
+
async write() {
|
|
83
|
+
events.push('write');
|
|
84
|
+
},
|
|
85
|
+
async read() {
|
|
86
|
+
return new Uint8Array();
|
|
87
|
+
},
|
|
88
|
+
async remove() { },
|
|
34
89
|
},
|
|
35
|
-
|
|
36
|
-
|
|
90
|
+
});
|
|
91
|
+
const draft = attachments.createDraft({ body: new Uint8Array([1]), originalName: 'profile.jpg' });
|
|
92
|
+
const service = new LucidAttachmentLifecycleService(attachments, makeStore({
|
|
37
93
|
async createOriginal() {
|
|
38
|
-
events.push('
|
|
39
|
-
return
|
|
40
|
-
},
|
|
41
|
-
async findOriginal() {
|
|
42
|
-
return null;
|
|
94
|
+
events.push('link');
|
|
95
|
+
return makeLink(attachment);
|
|
43
96
|
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
async restoreOwner() { },
|
|
49
|
-
async remove() { },
|
|
50
|
-
});
|
|
51
|
-
await service.attach({ type: 'users', id: '42', field: 'avatar' }, {
|
|
52
|
-
body: new Uint8Array(),
|
|
53
|
-
originalName: 'profile.jpg',
|
|
54
|
-
});
|
|
55
|
-
assert.deepEqual(events, ['write', 'persist']);
|
|
97
|
+
}));
|
|
98
|
+
await service.attach({ type: 'users', id: '42', field: 'avatar' }, draft);
|
|
99
|
+
assert.isTrue(draft.isPersisted);
|
|
100
|
+
assert.deepEqual(events, ['write', 'link']);
|
|
56
101
|
});
|
|
57
|
-
test('removes a new file when
|
|
102
|
+
test('removes a new file when blob or link persistence fails', async ({ assert }) => {
|
|
58
103
|
const removed = [];
|
|
59
104
|
const service = new LucidAttachmentLifecycleService({
|
|
60
105
|
async create() {
|
|
@@ -63,144 +108,105 @@ test.group('LucidAttachmentLifecycleService', () => {
|
|
|
63
108
|
async remove(value) {
|
|
64
109
|
removed.push(value);
|
|
65
110
|
},
|
|
66
|
-
}, {
|
|
111
|
+
}, makeStore({
|
|
67
112
|
async createOriginal() {
|
|
68
113
|
throw new Error('database unavailable');
|
|
69
114
|
},
|
|
70
|
-
|
|
71
|
-
return null;
|
|
72
|
-
},
|
|
73
|
-
async listVariants() {
|
|
74
|
-
return [];
|
|
75
|
-
},
|
|
76
|
-
async releaseOwner() { },
|
|
77
|
-
async restoreOwner() { },
|
|
78
|
-
async remove() { },
|
|
79
|
-
});
|
|
115
|
+
}));
|
|
80
116
|
await assert.rejects(() => service.attach({ type: 'users', id: '42', field: 'avatar' }, {
|
|
81
117
|
body: new Uint8Array(),
|
|
82
118
|
originalName: 'profile.jpg',
|
|
83
119
|
}), 'database unavailable');
|
|
84
120
|
assert.deepEqual(removed, [attachment]);
|
|
85
121
|
});
|
|
86
|
-
test('replaces
|
|
122
|
+
test('replaces a link before purging its unreferenced blob', async ({ assert }) => {
|
|
87
123
|
const events = [];
|
|
88
124
|
const previousAttachment = { ...attachment, id: 'previous-id', path: 'users/42/previous.jpg' };
|
|
89
125
|
const currentAttachment = { ...attachment, id: 'current-id', path: 'users/42/current.jpg' };
|
|
90
|
-
const previous =
|
|
91
|
-
const current =
|
|
126
|
+
const previous = makeLink(previousAttachment);
|
|
127
|
+
const current = makeLink(currentAttachment);
|
|
92
128
|
const service = new LucidAttachmentLifecycleService({
|
|
93
129
|
async create() {
|
|
94
|
-
events.push('write
|
|
130
|
+
events.push('write');
|
|
95
131
|
return currentAttachment;
|
|
96
132
|
},
|
|
97
133
|
async remove(value) {
|
|
98
134
|
events.push(`remove-file:${value.id}`);
|
|
99
135
|
},
|
|
100
|
-
}, {
|
|
136
|
+
}, makeStore({
|
|
101
137
|
async createOriginal() {
|
|
102
|
-
events.push('
|
|
138
|
+
events.push('create-link');
|
|
103
139
|
return current;
|
|
104
140
|
},
|
|
105
141
|
async findOriginal() {
|
|
106
142
|
return previous;
|
|
107
143
|
},
|
|
108
|
-
async listVariants() {
|
|
109
|
-
return [];
|
|
110
|
-
},
|
|
111
144
|
async releaseOwner() {
|
|
112
|
-
events.push('release-
|
|
145
|
+
events.push('release-link');
|
|
113
146
|
},
|
|
114
|
-
async
|
|
115
|
-
|
|
116
|
-
|
|
147
|
+
async remove() {
|
|
148
|
+
events.push('remove-link');
|
|
149
|
+
return [makeBlob(previousAttachment)];
|
|
117
150
|
},
|
|
118
|
-
});
|
|
119
|
-
|
|
151
|
+
}));
|
|
152
|
+
await service.replace({ type: 'users', id: '42', field: 'avatar' }, {
|
|
120
153
|
body: new Uint8Array(),
|
|
121
154
|
originalName: 'profile.jpg',
|
|
122
155
|
});
|
|
123
|
-
assert.equal(row, current);
|
|
124
156
|
assert.deepEqual(events, [
|
|
125
|
-
'write
|
|
126
|
-
'release-
|
|
127
|
-
'
|
|
128
|
-
'remove-
|
|
157
|
+
'write',
|
|
158
|
+
'release-link',
|
|
159
|
+
'create-link',
|
|
160
|
+
'remove-link',
|
|
129
161
|
'remove-file:previous-id',
|
|
130
162
|
]);
|
|
131
163
|
});
|
|
132
|
-
test('
|
|
133
|
-
const
|
|
134
|
-
const previous = makeRow(attachment, 'previous-id');
|
|
135
|
-
const currentAttachment = { ...attachment, id: 'current-id', path: 'users/42/current.jpg' };
|
|
164
|
+
test('only removes files for blobs that became unreferenced', async ({ assert }) => {
|
|
165
|
+
const removed = [];
|
|
136
166
|
const service = new LucidAttachmentLifecycleService({
|
|
137
167
|
async create() {
|
|
138
|
-
|
|
139
|
-
return currentAttachment;
|
|
168
|
+
return attachment;
|
|
140
169
|
},
|
|
141
170
|
async remove(value) {
|
|
142
|
-
|
|
143
|
-
},
|
|
144
|
-
}, {
|
|
145
|
-
async createOriginal() {
|
|
146
|
-
throw new Error('database unavailable');
|
|
171
|
+
removed.push(value.id);
|
|
147
172
|
},
|
|
173
|
+
}, makeStore({
|
|
148
174
|
async findOriginal() {
|
|
149
|
-
return
|
|
175
|
+
return makeLink(attachment);
|
|
150
176
|
},
|
|
151
|
-
async
|
|
177
|
+
async remove() {
|
|
152
178
|
return [];
|
|
153
179
|
},
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
async restoreOwner() {
|
|
158
|
-
events.push('restore-previous');
|
|
159
|
-
},
|
|
160
|
-
async remove() { },
|
|
161
|
-
});
|
|
162
|
-
await assert.rejects(() => service.replace({ type: 'users', id: '42', field: 'avatar' }, {
|
|
163
|
-
body: new Uint8Array(),
|
|
164
|
-
originalName: 'profile.jpg',
|
|
165
|
-
}), 'database unavailable');
|
|
166
|
-
assert.deepEqual(events, [
|
|
167
|
-
'write-current',
|
|
168
|
-
'release-previous',
|
|
169
|
-
'restore-previous',
|
|
170
|
-
'remove-file:current-id',
|
|
171
|
-
]);
|
|
180
|
+
}));
|
|
181
|
+
await service.detach({ type: 'users', id: '42', field: 'avatar' });
|
|
182
|
+
assert.deepEqual(removed, []);
|
|
172
183
|
});
|
|
173
|
-
test('
|
|
174
|
-
const
|
|
175
|
-
const
|
|
176
|
-
const original = makeRow(attachment);
|
|
177
|
-
const variant = makeRow({ ...attachment, id: 'variant-id', path: 'users/42/thumbnail.webp' });
|
|
184
|
+
test('adds and removes ordered collection links', async ({ assert }) => {
|
|
185
|
+
const item = makeLink(attachment);
|
|
186
|
+
const removed = [];
|
|
178
187
|
const service = new LucidAttachmentLifecycleService({
|
|
179
188
|
async create() {
|
|
180
189
|
return attachment;
|
|
181
190
|
},
|
|
182
191
|
async remove(value) {
|
|
183
|
-
|
|
184
|
-
},
|
|
185
|
-
}, {
|
|
186
|
-
async createOriginal() {
|
|
187
|
-
return original;
|
|
192
|
+
removed.push(value.id);
|
|
188
193
|
},
|
|
189
|
-
|
|
190
|
-
|
|
194
|
+
}, makeStore({
|
|
195
|
+
async createCollectionItem() {
|
|
196
|
+
return item;
|
|
191
197
|
},
|
|
192
|
-
async
|
|
193
|
-
return
|
|
198
|
+
async findCollectionItem() {
|
|
199
|
+
return item;
|
|
194
200
|
},
|
|
195
|
-
async
|
|
196
|
-
|
|
197
|
-
async remove(row) {
|
|
198
|
-
removedRows.push(row.id);
|
|
201
|
+
async removeCollectionItem() {
|
|
202
|
+
return [makeBlob(attachment)];
|
|
199
203
|
},
|
|
200
|
-
});
|
|
201
|
-
await service.
|
|
202
|
-
|
|
203
|
-
assert.
|
|
204
|
+
}));
|
|
205
|
+
const added = await service.add({ type: 'users', id: '42', field: 'gallery' }, { body: new Uint8Array(), originalName: 'profile.jpg' });
|
|
206
|
+
const didRemove = await service.removeCollectionItem({ type: 'users', id: '42', field: 'gallery' }, added.id);
|
|
207
|
+
assert.equal(added.id, item.id);
|
|
208
|
+
assert.isTrue(didRemove);
|
|
209
|
+
assert.deepEqual(removed, [attachment.id]);
|
|
204
210
|
});
|
|
205
211
|
});
|
|
206
212
|
//# sourceMappingURL=lucid_attachment_lifecycle_service.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lucid_attachment_lifecycle_service.spec.js","sourceRoot":"","sources":["../../tests/lucid_attachment_lifecycle_service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"lucid_attachment_lifecycle_service.spec.js","sourceRoot":"","sources":["../../tests/lucid_attachment_lifecycle_service.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lucid_attachment_relation.spec.d.ts","sourceRoot":"","sources":["../../tests/lucid_attachment_relation.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
8
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
11
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12
|
+
};
|
|
13
|
+
import { setApp } from "@adonisjs/core/services/app";
|
|
14
|
+
import { BaseModel, column } from "@adonisjs/lucid/orm";
|
|
15
|
+
import { test } from "@japa/runner";
|
|
16
|
+
import { attachmentRelation, attachmentsRelation, } from "../index.js";
|
|
17
|
+
import { AttachmentService } from "../src/core/attachment_service.js";
|
|
18
|
+
import { AttachmentModel } from "../src/integrations/lucid/models/attachment_model.js";
|
|
19
|
+
import { LucidAttachmentStore } from "../src/integrations/lucid/persistence/lucid_attachment_store.js";
|
|
20
|
+
import { createLucidTestDatabase } from "./helpers/lucid_test_database.js";
|
|
21
|
+
class RelationUser extends BaseModel {
|
|
22
|
+
static table = "relation_users";
|
|
23
|
+
static selfAssignPrimaryKey = true;
|
|
24
|
+
}
|
|
25
|
+
__decorate([
|
|
26
|
+
column({ isPrimary: true })
|
|
27
|
+
], RelationUser.prototype, "id", void 0);
|
|
28
|
+
__decorate([
|
|
29
|
+
column()
|
|
30
|
+
], RelationUser.prototype, "name", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
attachmentRelation({
|
|
33
|
+
disk: "decorator",
|
|
34
|
+
folder: ({ model }) => `avatars/${model.id}`,
|
|
35
|
+
rename: false,
|
|
36
|
+
})
|
|
37
|
+
], RelationUser.prototype, "avatar", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
attachmentsRelation({
|
|
40
|
+
folder: ({ model }) => `gallery/${model.id}`,
|
|
41
|
+
rename: false,
|
|
42
|
+
})
|
|
43
|
+
], RelationUser.prototype, "gallery", void 0);
|
|
44
|
+
let database;
|
|
45
|
+
let attachments;
|
|
46
|
+
let removed;
|
|
47
|
+
let writes;
|
|
48
|
+
let queued;
|
|
49
|
+
let nextId = 0;
|
|
50
|
+
function createDraft(name, options = {}) {
|
|
51
|
+
return attachments.createDraft({
|
|
52
|
+
body: Buffer.from(name),
|
|
53
|
+
originalName: name,
|
|
54
|
+
mimeType: "text/plain",
|
|
55
|
+
}, options);
|
|
56
|
+
}
|
|
57
|
+
async function createUser(id = "user-1") {
|
|
58
|
+
const user = new RelationUser();
|
|
59
|
+
user.id = id;
|
|
60
|
+
user.name = id;
|
|
61
|
+
await user.save();
|
|
62
|
+
return user;
|
|
63
|
+
}
|
|
64
|
+
async function getAvatarOrFail(user) {
|
|
65
|
+
const avatar = await user.avatar.get();
|
|
66
|
+
if (!avatar) {
|
|
67
|
+
throw new Error("Expected a persisted avatar link");
|
|
68
|
+
}
|
|
69
|
+
return avatar;
|
|
70
|
+
}
|
|
71
|
+
test.group("Lucid attachment relations", (group) => {
|
|
72
|
+
group.setup(async () => {
|
|
73
|
+
database = await createLucidTestDatabase();
|
|
74
|
+
RelationUser.useAdapter(database.modelAdapter());
|
|
75
|
+
await database
|
|
76
|
+
.connection()
|
|
77
|
+
.schema.createTable("relation_users", (table) => {
|
|
78
|
+
table.string("id").primary();
|
|
79
|
+
table.string("name").notNullable().unique();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
group.each.setup(async () => {
|
|
83
|
+
await database.from("attachments").delete();
|
|
84
|
+
await database.from("relation_users").delete();
|
|
85
|
+
removed = [];
|
|
86
|
+
writes = [];
|
|
87
|
+
queued = [];
|
|
88
|
+
nextId = 0;
|
|
89
|
+
attachments = new AttachmentService({
|
|
90
|
+
defaultDisk: "fs",
|
|
91
|
+
defaults: { disk: "config", folder: "config" },
|
|
92
|
+
createId: () => `attachment-${++nextId}`,
|
|
93
|
+
queue: {
|
|
94
|
+
async enqueue(job) {
|
|
95
|
+
queued.push(job.attachmentId);
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
storage: {
|
|
99
|
+
async write(input) {
|
|
100
|
+
writes.push({ disk: input.disk, path: input.path });
|
|
101
|
+
},
|
|
102
|
+
async read() {
|
|
103
|
+
return new Uint8Array();
|
|
104
|
+
},
|
|
105
|
+
async remove(location) {
|
|
106
|
+
removed.push(location.path);
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
setApp({
|
|
111
|
+
container: {
|
|
112
|
+
async make(binding) {
|
|
113
|
+
if (binding !== "jrmc.attachment") {
|
|
114
|
+
throw new Error(`Unexpected binding: ${binding}`);
|
|
115
|
+
}
|
|
116
|
+
return attachments;
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
group.teardown(async () => {
|
|
122
|
+
await database.manager.closeAll();
|
|
123
|
+
});
|
|
124
|
+
test("stages singular changes until the Lucid model is saved", async ({ assert, }) => {
|
|
125
|
+
const user = new RelationUser();
|
|
126
|
+
user.id = "user-1";
|
|
127
|
+
user.name = "user-1";
|
|
128
|
+
const first = createDraft("first.txt");
|
|
129
|
+
user.avatar.attach(first);
|
|
130
|
+
assert.isFalse(first.isPersisted);
|
|
131
|
+
await user.save();
|
|
132
|
+
const original = await getAvatarOrFail(user);
|
|
133
|
+
assert.isTrue(first.isPersisted);
|
|
134
|
+
assert.equal(original.attachableType, "relation_users");
|
|
135
|
+
assert.equal(original.attachableId, user.id);
|
|
136
|
+
assert.equal(original.field, "avatar");
|
|
137
|
+
assert.equal(first.disk, "decorator");
|
|
138
|
+
assert.equal(first.path, "avatars/user-1/first.txt");
|
|
139
|
+
assert.equal((await user.avatar.get())?.id, original.id);
|
|
140
|
+
user.avatar.attach(createDraft("duplicate.txt"));
|
|
141
|
+
await assert.rejects(() => user.save(), /already has an attachment/);
|
|
142
|
+
const replacement = createDraft("replacement.txt", {
|
|
143
|
+
disk: "manager",
|
|
144
|
+
folder: "imports",
|
|
145
|
+
});
|
|
146
|
+
user.avatar.set(replacement);
|
|
147
|
+
await user.save();
|
|
148
|
+
const current = await getAvatarOrFail(user);
|
|
149
|
+
await new LucidAttachmentStore().createVariant(current.attachment, "thumbnail", {
|
|
150
|
+
id: "variant-id",
|
|
151
|
+
disk: "manager",
|
|
152
|
+
path: "imports/thumbnail.txt",
|
|
153
|
+
name: "thumbnail.txt",
|
|
154
|
+
originalName: "replacement.txt",
|
|
155
|
+
mimeType: "text/plain",
|
|
156
|
+
extname: "txt",
|
|
157
|
+
size: 1,
|
|
158
|
+
});
|
|
159
|
+
assert.equal(replacement.path, "imports/replacement.txt");
|
|
160
|
+
assert.deepEqual((await user.avatar.variants()).map((variant) => variant.id), ["variant-id"]);
|
|
161
|
+
assert.isTrue(await user.avatar.regenerateVariants(["thumbnail"]));
|
|
162
|
+
assert.deepEqual(queued, [current.attachmentId]);
|
|
163
|
+
user.avatar.detach();
|
|
164
|
+
await user.save();
|
|
165
|
+
assert.isNull(await user.avatar.get());
|
|
166
|
+
assert.sameDeepMembers(removed, [
|
|
167
|
+
first.toAttachment().path,
|
|
168
|
+
replacement.toAttachment().path,
|
|
169
|
+
"imports/thumbnail.txt",
|
|
170
|
+
]);
|
|
171
|
+
assert.deepEqual(writes, [
|
|
172
|
+
{ disk: "decorator", path: "avatars/user-1/first.txt" },
|
|
173
|
+
{ disk: "manager", path: "imports/replacement.txt" },
|
|
174
|
+
]);
|
|
175
|
+
});
|
|
176
|
+
test("stages ordered collection changes until the Lucid model is saved", async ({ assert, }) => {
|
|
177
|
+
const user = await createUser();
|
|
178
|
+
user.gallery.add(createDraft("first.txt"));
|
|
179
|
+
user.gallery.add(createDraft("second.txt"));
|
|
180
|
+
user.gallery.add(createDraft("before.txt"), 0);
|
|
181
|
+
await user.save();
|
|
182
|
+
const [before, first, second] = await user.gallery.all();
|
|
183
|
+
if (!before || !first || !second) {
|
|
184
|
+
throw new Error("Expected persisted gallery links");
|
|
185
|
+
}
|
|
186
|
+
assert.deepEqual((await user.gallery.all()).map((item) => item.id), [before.id, first.id, second.id]);
|
|
187
|
+
user.gallery.move(second.id, 0);
|
|
188
|
+
await user.save();
|
|
189
|
+
assert.deepEqual((await user.gallery.all()).map((item) => item.id), [second.id, before.id, first.id]);
|
|
190
|
+
user.gallery.remove(before.id);
|
|
191
|
+
user.gallery.remove("missing-id");
|
|
192
|
+
await user.save();
|
|
193
|
+
user.gallery.replaceAll([
|
|
194
|
+
createDraft("replacement-1.txt"),
|
|
195
|
+
createDraft("replacement-2.txt"),
|
|
196
|
+
]);
|
|
197
|
+
await user.save();
|
|
198
|
+
const replacement = await user.gallery.all();
|
|
199
|
+
assert.deepEqual(replacement.map((item) => item.position), [0, 1]);
|
|
200
|
+
user.gallery.clear();
|
|
201
|
+
await user.save();
|
|
202
|
+
assert.deepEqual(await user.gallery.all(), []);
|
|
203
|
+
assert.equal(removed.length, 5);
|
|
204
|
+
});
|
|
205
|
+
test("can flush a staged relation explicitly for a persisted owner", async ({ assert }) => {
|
|
206
|
+
const user = await createUser();
|
|
207
|
+
const draft = createDraft("immediate.txt");
|
|
208
|
+
user.avatar.set(draft);
|
|
209
|
+
const avatar = await user.avatar.persist();
|
|
210
|
+
assert.isNotNull(avatar);
|
|
211
|
+
assert.isTrue(draft.isPersisted);
|
|
212
|
+
assert.equal((await user.avatar.get())?.id, avatar?.id);
|
|
213
|
+
});
|
|
214
|
+
test("requires the Lucid owner to be persisted", async ({ assert }) => {
|
|
215
|
+
const user = new RelationUser();
|
|
216
|
+
user.id = "user-1";
|
|
217
|
+
await assert.rejects(() => user.avatar.get(), /require a persisted Lucid model/);
|
|
218
|
+
});
|
|
219
|
+
test("uses the owner transaction and cleans up a new file after rollback", async ({ assert, }) => {
|
|
220
|
+
const user = await createUser();
|
|
221
|
+
const draft = createDraft("rollback.txt");
|
|
222
|
+
await assert.rejects(() => database.transaction(async (trx) => {
|
|
223
|
+
const transactionalUser = await RelationUser.query({ client: trx })
|
|
224
|
+
.where("id", user.id)
|
|
225
|
+
.firstOrFail();
|
|
226
|
+
transactionalUser.useTransaction(trx);
|
|
227
|
+
transactionalUser.avatar.attach(draft);
|
|
228
|
+
await transactionalUser.save();
|
|
229
|
+
assert.isNotNull(await transactionalUser.avatar.get());
|
|
230
|
+
throw new Error("Rollback requested");
|
|
231
|
+
}), /Rollback requested/);
|
|
232
|
+
assert.isNull(await user.avatar.get());
|
|
233
|
+
assert.deepEqual(removed, [draft.path]);
|
|
234
|
+
});
|
|
235
|
+
test("defers file deletion until an owner transaction commits", async ({ assert }) => {
|
|
236
|
+
const user = await createUser();
|
|
237
|
+
const draft = createDraft("avatar.txt");
|
|
238
|
+
user.avatar.attach(draft);
|
|
239
|
+
await user.save();
|
|
240
|
+
removed = [];
|
|
241
|
+
await assert.rejects(() => database.transaction(async (trx) => {
|
|
242
|
+
const transactionalUser = await RelationUser.query({ client: trx })
|
|
243
|
+
.where("id", user.id)
|
|
244
|
+
.firstOrFail();
|
|
245
|
+
transactionalUser.useTransaction(trx);
|
|
246
|
+
transactionalUser.avatar.detach();
|
|
247
|
+
await transactionalUser.save();
|
|
248
|
+
assert.isNull(await transactionalUser.avatar.get());
|
|
249
|
+
throw new Error("Rollback requested");
|
|
250
|
+
}), /Rollback requested/);
|
|
251
|
+
assert.equal((await user.avatar.get())?.attachmentId, draft.id);
|
|
252
|
+
assert.deepEqual(removed, []);
|
|
253
|
+
});
|
|
254
|
+
test("purges relation links and unreferenced blobs when the owner is deleted", async ({ assert, }) => {
|
|
255
|
+
const user = await createUser();
|
|
256
|
+
user.avatar.attach(createDraft("avatar.txt"));
|
|
257
|
+
user.gallery.add(createDraft("gallery.txt"));
|
|
258
|
+
await user.save();
|
|
259
|
+
const avatar = await getAvatarOrFail(user);
|
|
260
|
+
const [gallery] = await user.gallery.all();
|
|
261
|
+
if (!gallery) {
|
|
262
|
+
throw new Error("Expected a persisted gallery link");
|
|
263
|
+
}
|
|
264
|
+
removed = [];
|
|
265
|
+
await user.delete();
|
|
266
|
+
assert.isNull(await user.avatar.get());
|
|
267
|
+
assert.deepEqual(await user.gallery.all(), []);
|
|
268
|
+
assert.isNull(await AttachmentModel.find(avatar.attachmentId));
|
|
269
|
+
assert.isNull(await AttachmentModel.find(gallery.attachmentId));
|
|
270
|
+
assert.sameDeepMembers(removed, [
|
|
271
|
+
avatar.toAttachment().path,
|
|
272
|
+
gallery.toAttachment().path,
|
|
273
|
+
]);
|
|
274
|
+
});
|
|
275
|
+
test("keeps a shared blob until its last owner link is deleted", async ({ assert }) => {
|
|
276
|
+
const firstUser = await createUser("user-1");
|
|
277
|
+
const secondUser = await createUser("user-2");
|
|
278
|
+
firstUser.avatar.attach(createDraft("shared.txt"));
|
|
279
|
+
await firstUser.save();
|
|
280
|
+
const firstLink = await getAvatarOrFail(firstUser);
|
|
281
|
+
secondUser.avatar.attachExisting(firstLink.attachmentId);
|
|
282
|
+
await secondUser.save();
|
|
283
|
+
const secondLink = await getAvatarOrFail(secondUser);
|
|
284
|
+
removed = [];
|
|
285
|
+
assert.notEqual(firstLink.id, secondLink.id);
|
|
286
|
+
assert.equal(firstLink.attachmentId, secondLink.attachmentId);
|
|
287
|
+
await firstUser.delete();
|
|
288
|
+
assert.isNotNull(await AttachmentModel.find(firstLink.attachmentId));
|
|
289
|
+
assert.deepEqual(removed, []);
|
|
290
|
+
await secondUser.delete();
|
|
291
|
+
assert.isNull(await AttachmentModel.find(firstLink.attachmentId));
|
|
292
|
+
assert.deepEqual(removed, [firstLink.toAttachment().path]);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
//# sourceMappingURL=lucid_attachment_relation.spec.js.map
|