@jrmc/adonis-attachment 5.0.0-beta.2 → 5.0.0-beta.4
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/index.d.ts +0 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +0 -1
- package/build/providers/attachment_provider.d.ts.map +1 -1
- package/build/providers/attachment_provider.js +10 -1
- package/build/services/regenerate_service.js +3 -3
- package/build/src/adapters/lock.d.ts +9 -0
- package/build/src/adapters/lock.d.ts.map +1 -0
- package/build/src/adapters/lock.js +21 -0
- package/build/src/attachment_manager.d.ts +4 -2
- package/build/src/attachment_manager.d.ts.map +1 -1
- package/build/src/attachment_manager.js +7 -1
- package/build/src/attachments/attachment.d.ts +1 -1
- package/build/src/attachments/attachment.js +1 -1
- package/build/src/controllers/attachments_controller.d.ts.map +1 -1
- package/build/src/controllers/attachments_controller.js +83 -74
- package/build/src/decorators/attachment.d.ts +3 -3
- package/build/src/decorators/attachment.d.ts.map +1 -1
- package/build/src/services/attachment/attachment_detachment_service.d.ts +19 -0
- package/build/src/services/attachment/attachment_detachment_service.d.ts.map +1 -0
- package/build/src/services/attachment/attachment_detachment_service.js +64 -0
- package/build/src/services/attachment/attachment_persister_service.d.ts +22 -0
- package/build/src/services/attachment/attachment_persister_service.d.ts.map +1 -0
- package/build/src/services/attachment/attachment_persister_service.js +93 -0
- package/build/src/services/attachment/attachment_recorder_service.d.ts +68 -0
- package/build/src/services/attachment/attachment_recorder_service.d.ts.map +1 -0
- package/build/src/services/attachment/attachment_recorder_service.js +119 -0
- package/build/src/services/attachment/attachment_transaction_service.d.ts +26 -0
- package/build/src/services/attachment/attachment_transaction_service.d.ts.map +1 -0
- package/build/src/services/attachment/attachment_transaction_service.js +43 -0
- package/build/src/services/attachment/attachment_utils.d.ts +35 -0
- package/build/src/services/attachment/attachment_utils.d.ts.map +1 -0
- package/build/src/services/attachment/attachment_utils.js +71 -0
- package/build/src/services/attachment/attachment_variant_service.d.ts +17 -0
- package/build/src/services/attachment/attachment_variant_service.d.ts.map +1 -0
- package/build/src/services/attachment/attachment_variant_service.js +72 -0
- package/build/src/services/attachment/index.d.ts +15 -0
- package/build/src/services/attachment/index.d.ts.map +1 -0
- package/build/src/services/attachment/index.js +15 -0
- package/build/src/services/attachment_service.d.ts +8 -0
- package/build/src/services/attachment_service.d.ts.map +1 -0
- package/build/src/services/attachment_service.js +7 -0
- package/build/src/services/variant/variant_generator_service.d.ts +24 -0
- package/build/src/services/variant/variant_generator_service.d.ts.map +1 -0
- package/build/src/services/variant/variant_generator_service.js +97 -0
- package/build/src/services/variant/variant_persister_service.d.ts +23 -0
- package/build/src/services/variant/variant_persister_service.d.ts.map +1 -0
- package/build/src/services/variant/variant_persister_service.js +60 -0
- package/build/src/services/variant/variant_purger_service.d.ts +15 -0
- package/build/src/services/variant/variant_purger_service.d.ts.map +1 -0
- package/build/src/services/variant/variant_purger_service.js +48 -0
- package/build/src/services/variant_service.d.ts +13 -0
- package/build/src/services/variant_service.d.ts.map +1 -0
- package/build/src/services/variant_service.js +58 -0
- package/build/src/types/attachment.d.ts +3 -3
- package/build/src/types/attachment.d.ts.map +1 -1
- package/build/src/types/index.d.ts +6 -0
- package/build/src/types/index.d.ts.map +1 -1
- package/build/src/types/index.js +6 -0
- package/build/src/types/lock.d.ts +14 -0
- package/build/src/types/lock.d.ts.map +1 -0
- package/build/src/types/lock.js +7 -0
- package/build/src/types/metadata.d.ts +6 -0
- package/build/src/types/metadata.d.ts.map +1 -1
- package/build/src/types/metadata.js +6 -0
- package/build/src/types/regenerate.d.ts +6 -0
- package/build/src/types/regenerate.d.ts.map +1 -1
- package/build/src/types/regenerate.js +6 -0
- package/build/src/types/service.d.ts +6 -0
- package/build/src/types/service.d.ts.map +1 -1
- package/build/src/types/service.js +6 -0
- package/build/src/utils/hooks.js +5 -5
- package/build/stubs/config.stub +102 -4
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -22
- package/build/src/converter_manager.d.ts +0 -13
- package/build/src/converter_manager.d.ts.map +0 -1
- package/build/src/converter_manager.js +0 -121
- package/build/src/services/record_with_attachment.d.ts +0 -33
- package/build/src/services/record_with_attachment.d.ts.map +0 -1
- package/build/src/services/record_with_attachment.js +0 -303
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jrmc/adonis-attachment",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Turn any field on your Lucid model to an attachment data type",
|
|
6
6
|
"engines": {
|
|
@@ -65,51 +65,56 @@
|
|
|
65
65
|
"./attachment_provider": "./build/providers/attachment_provider.js"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@poppinss/defer": "^1.1.
|
|
68
|
+
"@poppinss/defer": "^1.1.2",
|
|
69
|
+
"@verrou/core": "^0.5.1",
|
|
69
70
|
"blurhash": "^2.0.5",
|
|
70
71
|
"execa": "^9.6.0",
|
|
71
|
-
"exifreader": "^4.
|
|
72
|
-
"file-type": "^
|
|
73
|
-
"mime-types": "^
|
|
72
|
+
"exifreader": "^4.31.1",
|
|
73
|
+
"file-type": "^21.0.0",
|
|
74
|
+
"mime-types": "^3.0.1"
|
|
74
75
|
},
|
|
75
76
|
"devDependencies": {
|
|
76
77
|
"@adonisjs/assembler": "^7.8.2",
|
|
77
|
-
"@adonisjs/core": "^6.
|
|
78
|
-
"@adonisjs/drive": "^3.
|
|
79
|
-
"@adonisjs/
|
|
80
|
-
"@adonisjs/
|
|
81
|
-
"@adonisjs/
|
|
78
|
+
"@adonisjs/core": "^6.19.0",
|
|
79
|
+
"@adonisjs/drive": "^3.4.1",
|
|
80
|
+
"@adonisjs/lock": "^1.1.1",
|
|
81
|
+
"@adonisjs/lucid": "^21.7.0",
|
|
82
|
+
"@adonisjs/prettier-config": "^1.4.5",
|
|
83
|
+
"@adonisjs/tsconfig": "^1.4.1",
|
|
82
84
|
"@japa/assert": "^4.0.1",
|
|
83
85
|
"@japa/expect-type": "^2.0.3",
|
|
84
86
|
"@japa/file-system": "^2.3.2",
|
|
85
|
-
"@japa/plugin-adonisjs": "^4.0.0",
|
|
86
87
|
"@japa/runner": "^4.1.0",
|
|
87
88
|
"@poppinss/utils": "^6.9.2",
|
|
88
|
-
"@swc/core": "^1.
|
|
89
|
-
"@types/luxon": "^3.
|
|
90
|
-
"@types/mime-types": "^
|
|
91
|
-
"@types/node": "^
|
|
92
|
-
"@types/sinon": "^17.0.
|
|
93
|
-
"better-sqlite3": "^
|
|
89
|
+
"@swc/core": "^1.12.9",
|
|
90
|
+
"@types/luxon": "^3.6.2",
|
|
91
|
+
"@types/mime-types": "^3.0.1",
|
|
92
|
+
"@types/node": "^24.0.10",
|
|
93
|
+
"@types/sinon": "^17.0.4",
|
|
94
|
+
"better-sqlite3": "^12.2.0",
|
|
94
95
|
"c8": "^10.1.3",
|
|
95
96
|
"copyfiles": "^2.4.1",
|
|
96
97
|
"del-cli": "^6.0.0",
|
|
97
|
-
"flydrive": "^1.
|
|
98
|
-
"luxon": "^3.
|
|
98
|
+
"flydrive": "^1.3.0",
|
|
99
|
+
"luxon": "^3.6.1",
|
|
99
100
|
"prettier": "^3.4.2",
|
|
100
|
-
"sharp": "^0.
|
|
101
|
-
"sinon": "^
|
|
101
|
+
"sharp": "^0.34.2",
|
|
102
|
+
"sinon": "^21.0.0",
|
|
102
103
|
"ts-node": "^10.9.2",
|
|
103
|
-
"typescript": "^5.
|
|
104
|
+
"typescript": "^5.3.3",
|
|
104
105
|
"vitepress": "^1.5.0"
|
|
105
106
|
},
|
|
106
107
|
"peerDependencies": {
|
|
107
108
|
"@adonisjs/core": "^6.12.1",
|
|
108
109
|
"@adonisjs/drive": "^3.2.0",
|
|
110
|
+
"@adonisjs/lock": "^1.1.1",
|
|
109
111
|
"@adonisjs/lucid": "^20.6.0 || ^21.0.0",
|
|
110
112
|
"sharp": "^0.33.0"
|
|
111
113
|
},
|
|
112
114
|
"peerDependenciesMeta": {
|
|
115
|
+
"@adonisjs/lock": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
113
118
|
"sharp": {
|
|
114
119
|
"optional": true
|
|
115
120
|
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Converter, ConverterInitializeAttributes } from './types/converter.js';
|
|
2
|
-
import type { Attachment, Variant } from './types/attachment.js';
|
|
3
|
-
export declare class ConverterManager {
|
|
4
|
-
#private;
|
|
5
|
-
constructor({ record, attributeName, options, filters }: ConverterInitializeAttributes);
|
|
6
|
-
run(): Promise<void>;
|
|
7
|
-
static generate({ key, attachment, converter }: {
|
|
8
|
-
key: string;
|
|
9
|
-
attachment: Attachment;
|
|
10
|
-
converter: Converter;
|
|
11
|
-
}): Promise<Variant | undefined>;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=converter_manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"converter_manager.d.ts","sourceRoot":"","sources":["../../src/converter_manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAA;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAgB,MAAM,uBAAuB,CAAA;AAS9E,qBAAa,gBAAgB;;gBAQf,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,6BAA6B;IAOhF,GAAG;WAyCI,QAAQ,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,EAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,SAAS,CAAA;KAAE;CA6FrH"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import logger from '@adonisjs/core/services/logger';
|
|
2
|
-
import string from '@adonisjs/core/helpers/string';
|
|
3
|
-
import db from '@adonisjs/lucid/services/db';
|
|
4
|
-
import attachmentManager from '../services/main.js';
|
|
5
|
-
import { streamToTempFile } from './utils/helpers.js';
|
|
6
|
-
export class ConverterManager {
|
|
7
|
-
#record;
|
|
8
|
-
#attributeName;
|
|
9
|
-
#options;
|
|
10
|
-
#filters;
|
|
11
|
-
constructor({ record, attributeName, options, filters }) {
|
|
12
|
-
this.#record = record;
|
|
13
|
-
this.#attributeName = attributeName;
|
|
14
|
-
this.#options = options;
|
|
15
|
-
this.#filters = filters;
|
|
16
|
-
}
|
|
17
|
-
async run() {
|
|
18
|
-
const attachments = this.#record.getAttachments({
|
|
19
|
-
attributeName: this.#attributeName,
|
|
20
|
-
});
|
|
21
|
-
const variants = [];
|
|
22
|
-
await this.#purge(attachments);
|
|
23
|
-
if (!attachments || !this.#options.variants || !this.#options.variants.length) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
for await (const key of this.#options.variants) {
|
|
27
|
-
if (this.#filters?.variants !== undefined && !this.#filters?.variants?.includes(key)) {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
const converter = (await attachmentManager.getConverter(key));
|
|
31
|
-
if (converter) {
|
|
32
|
-
for await (const attachment of attachments) {
|
|
33
|
-
const variant = await ConverterManager.generate({
|
|
34
|
-
key,
|
|
35
|
-
attachment,
|
|
36
|
-
converter
|
|
37
|
-
});
|
|
38
|
-
if (variant) {
|
|
39
|
-
variants.push(variant);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return this.#commit(attachments, () => {
|
|
45
|
-
for (let i = 0; i < variants.length; i++) {
|
|
46
|
-
attachmentManager.remove(variants[i]);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
static async generate({ key, attachment, converter }) {
|
|
51
|
-
let input = attachment.input;
|
|
52
|
-
if (!input) {
|
|
53
|
-
input = await streamToTempFile(await attachment.getStream());
|
|
54
|
-
}
|
|
55
|
-
const output = await converter.handle({
|
|
56
|
-
input,
|
|
57
|
-
options: converter.options,
|
|
58
|
-
});
|
|
59
|
-
if (output === undefined) {
|
|
60
|
-
// throw new errors.E_CANNOT_PATH_BY_CONVERTER()
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const variant = await attachment.createVariant(key, output);
|
|
64
|
-
if (converter.options.blurhash) {
|
|
65
|
-
if ((typeof converter.options.blurhash !== 'boolean' &&
|
|
66
|
-
converter.options.blurhash.enabled === true) ||
|
|
67
|
-
converter.options.blurhash === true) {
|
|
68
|
-
try {
|
|
69
|
-
const options = typeof converter.options.blurhash !== 'boolean'
|
|
70
|
-
? converter.options.blurhash
|
|
71
|
-
: undefined;
|
|
72
|
-
await variant.generateBlurhash(options);
|
|
73
|
-
}
|
|
74
|
-
catch (error) {
|
|
75
|
-
logger.error(error.message);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
await attachmentManager.write(variant);
|
|
80
|
-
return variant;
|
|
81
|
-
}
|
|
82
|
-
async #commit(attachments, rollback) {
|
|
83
|
-
const Model = this.#record.row.constructor;
|
|
84
|
-
const id = this.#record.row.$attributes['id'];
|
|
85
|
-
const data = {};
|
|
86
|
-
const index = string.snakeCase(this.#attributeName);
|
|
87
|
-
if (Array.isArray(this.#record.row.$original[this.#attributeName])) {
|
|
88
|
-
data[index] = JSON.stringify(attachments.map((att) => att.toObject()));
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
data[index] = JSON.stringify(attachments[0].toObject());
|
|
92
|
-
}
|
|
93
|
-
const trx = await db.transaction();
|
|
94
|
-
trx.after('rollback', rollback);
|
|
95
|
-
try {
|
|
96
|
-
await trx.query().from(Model.table).where('id', id).update(data);
|
|
97
|
-
return trx.commit();
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
return trx.rollback();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
async #purge(attachments) {
|
|
104
|
-
return Promise.all(attachments.map(async (attachment) => {
|
|
105
|
-
if (attachment.variants) {
|
|
106
|
-
await Promise.all(attachment.variants.map(async (variant) => {
|
|
107
|
-
if (this.#filters?.variants !== undefined && !this.#filters?.variants?.includes(variant.key)) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
return attachmentManager.remove(variant);
|
|
111
|
-
}));
|
|
112
|
-
if (this.#filters?.variants !== undefined) {
|
|
113
|
-
attachment.variants = await attachment.variants.filter((variant) => !this.#filters?.variants?.includes(variant.key));
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
attachment.variants = [];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { RowWithAttachment } from '../types/mixin.js';
|
|
2
|
-
import type { Attachment as AttachmentType } from '../types/attachment.js';
|
|
3
|
-
import type { RecordWithAttachment as RecordWithAttachmentImplementation } from '../types/service.js';
|
|
4
|
-
import type { RegenerateOptions } from '../types/regenerate.js';
|
|
5
|
-
export default class RecordWithAttachment implements RecordWithAttachmentImplementation {
|
|
6
|
-
#private;
|
|
7
|
-
constructor(row: RowWithAttachment);
|
|
8
|
-
/**
|
|
9
|
-
* During commit, we should cleanup the old detached files
|
|
10
|
-
*/
|
|
11
|
-
commit(): Promise<void>;
|
|
12
|
-
/**
|
|
13
|
-
* During rollback we should remove the attached files.
|
|
14
|
-
*/
|
|
15
|
-
rollback(): Promise<void>;
|
|
16
|
-
persist(): Promise<void>;
|
|
17
|
-
transaction(options?: {
|
|
18
|
-
enabledRollback: boolean;
|
|
19
|
-
}): Promise<void>;
|
|
20
|
-
preComputeUrl(): Promise<void>;
|
|
21
|
-
setKeyId(): Promise<void>;
|
|
22
|
-
generateVariants(): Promise<void>;
|
|
23
|
-
regenerateVariants(options?: RegenerateOptions): Promise<void>;
|
|
24
|
-
detach(): Promise<PromiseSettledResult<void>[]>;
|
|
25
|
-
detachAll(): Promise<PromiseSettledResult<void>[]>;
|
|
26
|
-
get row(): RowWithAttachment;
|
|
27
|
-
getAttachments(options: {
|
|
28
|
-
attributeName: string;
|
|
29
|
-
requiredOriginal?: boolean;
|
|
30
|
-
requiredDirty?: boolean;
|
|
31
|
-
}): AttachmentType[];
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=record_with_attachment.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"record_with_attachment.d.ts","sourceRoot":"","sources":["../../../src/services/record_with_attachment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAgB,MAAM,wBAAwB,CAAA;AACxF,OAAO,KAAK,EAAE,oBAAoB,IAAI,kCAAkC,EAAE,MAAM,qBAAqB,CAAA;AACrG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAW/D,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,kCAAkC;;gBAGzE,GAAG,EAAE,iBAAiB;IAWlC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ7B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiDxB,WAAW,CAAC,OAAO;;KAA4B,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/D,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB9B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BzB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BjC,kBAAkB,CAAC,OAAO,GAAE,iBAAsB;IAmClD,MAAM;IA2CN,SAAS;IAkBf,IAAI,GAAG,sBAEN;IAED,cAAc,CAAC,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE;CAwEvG"}
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import logger from '@adonisjs/core/services/logger';
|
|
2
|
-
import encryption from '@adonisjs/core/services/encryption';
|
|
3
|
-
import attachmentManager from '../../services/main.js';
|
|
4
|
-
import { defaultStateAttributeMixin } from '../utils/default_values.js';
|
|
5
|
-
import { Attachment } from '../attachments/attachment.js';
|
|
6
|
-
import { optionsSym } from '../utils/symbols.js';
|
|
7
|
-
import { ConverterManager } from '../converter_manager.js';
|
|
8
|
-
import { E_CANNOT_CREATE_VARIANT } from '../errors.js';
|
|
9
|
-
export default class RecordWithAttachment {
|
|
10
|
-
#row;
|
|
11
|
-
constructor(row) {
|
|
12
|
-
this.#row = row;
|
|
13
|
-
if (!this.#row.$attachments) {
|
|
14
|
-
/**
|
|
15
|
-
* Empty previous $attachments
|
|
16
|
-
*/
|
|
17
|
-
this.#row.$attachments = structuredClone(defaultStateAttributeMixin);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* During commit, we should cleanup the old detached files
|
|
22
|
-
*/
|
|
23
|
-
async commit() {
|
|
24
|
-
await Promise.allSettled(this.#row.$attachments.detached.map((attachment) => attachmentManager.remove(attachment)));
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* During rollback we should remove the attached files.
|
|
28
|
-
*/
|
|
29
|
-
async rollback() {
|
|
30
|
-
await Promise.allSettled(this.#row.$attachments.attached.map((attachment) => attachmentManager.remove(attachment)));
|
|
31
|
-
}
|
|
32
|
-
async persist() {
|
|
33
|
-
const attachmentAttributeNames = this.#getDirtyAttributeNamesOfAttachment();
|
|
34
|
-
/**
|
|
35
|
-
* Persist attachments before saving the row to the database. This
|
|
36
|
-
* way if file saving fails we will not write anything to the
|
|
37
|
-
* database
|
|
38
|
-
*/
|
|
39
|
-
await Promise.all(attachmentAttributeNames.map(async (name) => {
|
|
40
|
-
const originalAttachments = this.#getOriginalAttachmentsByAttributeName(name);
|
|
41
|
-
const newAttachments = this.#getAttachmentsByAttributeName(name);
|
|
42
|
-
const options = this.#getOptionsByAttributeName(name);
|
|
43
|
-
/**
|
|
44
|
-
* Skip when the attachment attributeName hasn't been updated
|
|
45
|
-
*/
|
|
46
|
-
if (!originalAttachments && !newAttachments) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* memorise attribute name for generate variants
|
|
51
|
-
*/
|
|
52
|
-
this.#row.$attachments.dirtied.push(name);
|
|
53
|
-
for (let i = 0; i < newAttachments.length; i++) {
|
|
54
|
-
if (originalAttachments.includes(newAttachments[i])) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* If there is a new file and its local then we must save this
|
|
59
|
-
* file.
|
|
60
|
-
*/
|
|
61
|
-
if (newAttachments[i]) {
|
|
62
|
-
newAttachments[i].setOptions(options).makeFolder(this.#row);
|
|
63
|
-
this.#row.$attachments.attached.push(newAttachments[i]);
|
|
64
|
-
/**
|
|
65
|
-
* Also write the file to the disk right away
|
|
66
|
-
*/
|
|
67
|
-
await attachmentManager.write(newAttachments[i]);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}));
|
|
71
|
-
}
|
|
72
|
-
async transaction(options = { enabledRollback: true }) {
|
|
73
|
-
try {
|
|
74
|
-
if (this.#row.$trx) {
|
|
75
|
-
this.#row.$trx.after('commit', () => this.commit());
|
|
76
|
-
if (options.enabledRollback) {
|
|
77
|
-
this.#row.$trx.after('rollback', () => this.rollback());
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
await this.commit();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
if (options.enabledRollback) {
|
|
86
|
-
await this.rollback();
|
|
87
|
-
}
|
|
88
|
-
throw error;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
async preComputeUrl() {
|
|
92
|
-
const attachmentAttributeNames = this.#getAttributeNamesOfAttachment();
|
|
93
|
-
await Promise.all(attachmentAttributeNames.map(async (name) => {
|
|
94
|
-
const options = this.#getOptionsByAttributeName(name);
|
|
95
|
-
if (this.#row.$attributes[name]) {
|
|
96
|
-
const attachments = this.#getAttachmentsByAttributeName(name);
|
|
97
|
-
for (let i = 0; i < attachments.length; i++) {
|
|
98
|
-
attachments[i].setOptions(options);
|
|
99
|
-
await attachmentManager.preComputeUrl(attachments[i]);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}));
|
|
103
|
-
}
|
|
104
|
-
async setKeyId() {
|
|
105
|
-
const attachmentAttributeNames = this.#getAttributeNamesOfAttachment();
|
|
106
|
-
await Promise.all(attachmentAttributeNames.map(async (name) => {
|
|
107
|
-
if (this.#row.$attributes[name]) {
|
|
108
|
-
const attachments = this.#getAttachmentsByAttributeName(name);
|
|
109
|
-
for (let i = 0; i < attachments.length; i++) {
|
|
110
|
-
const { disk, folder, meta, rename } = attachments[i].options;
|
|
111
|
-
const model = this.#row.constructor;
|
|
112
|
-
const key = encryption.encrypt({
|
|
113
|
-
model: model.table,
|
|
114
|
-
id: this.#row.$attributes['id'],
|
|
115
|
-
attribute: name,
|
|
116
|
-
options: {
|
|
117
|
-
disk,
|
|
118
|
-
folder,
|
|
119
|
-
meta,
|
|
120
|
-
rename
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
attachments[i].setKeyId(key);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
async generateVariants() {
|
|
129
|
-
/* this.#row.$dirty is not avalable in afterSave hooks */
|
|
130
|
-
const attachmentAttributeNames = this.#row.$attachments.dirtied;
|
|
131
|
-
/**
|
|
132
|
-
* For all properties Attachment
|
|
133
|
-
* Launch async generation variants
|
|
134
|
-
*/
|
|
135
|
-
for await (const name of attachmentAttributeNames) {
|
|
136
|
-
const record = this;
|
|
137
|
-
attachmentManager.queue.push({
|
|
138
|
-
name: `${this.#row.constructor.name}-${name}`,
|
|
139
|
-
async run() {
|
|
140
|
-
const converterManager = new ConverterManager({
|
|
141
|
-
record,
|
|
142
|
-
attributeName: name,
|
|
143
|
-
options: record.#getOptionsByAttributeName(name),
|
|
144
|
-
});
|
|
145
|
-
await converterManager.run();
|
|
146
|
-
},
|
|
147
|
-
})
|
|
148
|
-
.onError = function (error) {
|
|
149
|
-
if (error.message) {
|
|
150
|
-
logger.error(error.message);
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
throw new E_CANNOT_CREATE_VARIANT([error]);
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
async regenerateVariants(options = {}) {
|
|
159
|
-
let attachmentAttributeNames;
|
|
160
|
-
if (options.attributes?.length) {
|
|
161
|
-
attachmentAttributeNames = options.attributes;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
attachmentAttributeNames = this.#getAttributeNamesOfAttachment();
|
|
165
|
-
}
|
|
166
|
-
for await (const name of attachmentAttributeNames) {
|
|
167
|
-
const record = this;
|
|
168
|
-
attachmentManager.queue.push({
|
|
169
|
-
name: `${this.#row.constructor.name}-${name}`,
|
|
170
|
-
async run() {
|
|
171
|
-
const converterManager = new ConverterManager({
|
|
172
|
-
record,
|
|
173
|
-
attributeName: name,
|
|
174
|
-
options: record.#getOptionsByAttributeName(name),
|
|
175
|
-
filters: {
|
|
176
|
-
variants: options.variants
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
await converterManager.run();
|
|
180
|
-
},
|
|
181
|
-
})
|
|
182
|
-
.onError = function (error) {
|
|
183
|
-
if (error.message) {
|
|
184
|
-
logger.error(error.message);
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
throw new E_CANNOT_CREATE_VARIANT([error]);
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
async detach() {
|
|
193
|
-
const attachmentAttributeNames = this.#getDirtyAttributeNamesOfAttachment();
|
|
194
|
-
/**
|
|
195
|
-
* Mark all original attachments for deletion
|
|
196
|
-
*/
|
|
197
|
-
return Promise.allSettled(attachmentAttributeNames.map((name) => {
|
|
198
|
-
let attachments = [];
|
|
199
|
-
const options = this.#getOptionsByAttributeName(name);
|
|
200
|
-
if (this.#row.$dirty[name] === null) {
|
|
201
|
-
attachments = this.#getOriginalAttachmentsByAttributeName(name);
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
const originalAttachments = this.#getOriginalAttachmentsByAttributeName(name);
|
|
205
|
-
const newAttachments = this.#getAttachmentsByAttributeName(name);
|
|
206
|
-
/**
|
|
207
|
-
* Clean Attachments changed
|
|
208
|
-
*/
|
|
209
|
-
for (let i = 0; i < originalAttachments.length; i++) {
|
|
210
|
-
if (newAttachments.includes(originalAttachments[i])) {
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* If there was an existing file, then we must get rid of it
|
|
215
|
-
*/
|
|
216
|
-
if (originalAttachments[i]) {
|
|
217
|
-
originalAttachments[i].setOptions(options);
|
|
218
|
-
attachments.push(originalAttachments[i]);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
for (let i = 0; i < attachments.length; i++) {
|
|
223
|
-
attachments[i].setOptions(options);
|
|
224
|
-
this.#row.$attachments.detached.push(attachments[i]);
|
|
225
|
-
}
|
|
226
|
-
}));
|
|
227
|
-
}
|
|
228
|
-
async detachAll() {
|
|
229
|
-
const attachmentAttributeNames = this.#getAttributeNamesOfAttachment();
|
|
230
|
-
/**
|
|
231
|
-
* Mark all attachments for deletion
|
|
232
|
-
*/
|
|
233
|
-
return Promise.allSettled(attachmentAttributeNames.map((name) => {
|
|
234
|
-
const options = this.#getOptionsByAttributeName(name);
|
|
235
|
-
const attachments = this.#getAttachmentsByAttributeName(name);
|
|
236
|
-
for (let i = 0; i < attachments.length; i++) {
|
|
237
|
-
attachments[i].setOptions(options);
|
|
238
|
-
this.#row.$attachments.detached.push(attachments[i]);
|
|
239
|
-
}
|
|
240
|
-
}));
|
|
241
|
-
}
|
|
242
|
-
get row() {
|
|
243
|
-
return this.#row;
|
|
244
|
-
}
|
|
245
|
-
getAttachments(options) {
|
|
246
|
-
let attachments;
|
|
247
|
-
if (options.requiredOriginal) {
|
|
248
|
-
attachments = this.#getOriginalAttachmentsByAttributeName(options.attributeName);
|
|
249
|
-
}
|
|
250
|
-
else if (options.requiredDirty) {
|
|
251
|
-
attachments = this.#getDirtyAttachmentsByAttributeName(options.attributeName);
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
attachments = this.#getAttachmentsByAttributeName(options.attributeName);
|
|
255
|
-
}
|
|
256
|
-
const opts = this.#getOptionsByAttributeName(options.attributeName);
|
|
257
|
-
attachments.map((attachment) => attachment.setOptions(opts).makeFolder(this.#row));
|
|
258
|
-
return attachments;
|
|
259
|
-
}
|
|
260
|
-
#getAttachmentsByAttributeName(name) {
|
|
261
|
-
if (Array.isArray(this.#row.$attributes[name])) {
|
|
262
|
-
return this.#row.$attributes[name];
|
|
263
|
-
}
|
|
264
|
-
return [this.#row.$attributes[name]];
|
|
265
|
-
}
|
|
266
|
-
#getOriginalAttachmentsByAttributeName(name) {
|
|
267
|
-
if (Array.isArray(this.#row.$original[name])) {
|
|
268
|
-
return this.#row.$original[name];
|
|
269
|
-
}
|
|
270
|
-
return [this.#row.$original[name]];
|
|
271
|
-
}
|
|
272
|
-
#getDirtyAttachmentsByAttributeName(name) {
|
|
273
|
-
if (Array.isArray(this.#row.$dirty[name])) {
|
|
274
|
-
return this.#row.$dirty[name];
|
|
275
|
-
}
|
|
276
|
-
return [this.#row.$dirty[name]];
|
|
277
|
-
}
|
|
278
|
-
#getOptionsByAttributeName(name) {
|
|
279
|
-
return this.#row.constructor.prototype[optionsSym]?.[name];
|
|
280
|
-
}
|
|
281
|
-
#getAttributeNamesOfAttachment() {
|
|
282
|
-
return Object.keys(this.#row.$attributes).filter((name) => {
|
|
283
|
-
const value = this.#row.$attributes[name];
|
|
284
|
-
return (value instanceof Attachment ||
|
|
285
|
-
(Array.isArray(value) && value.every((item) => item instanceof Attachment)));
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
#getDirtyAttributeNamesOfAttachment() {
|
|
289
|
-
return Object.keys(this.#row.$dirty).filter((name) => {
|
|
290
|
-
const dirtyValue = this.#row.$dirty[name];
|
|
291
|
-
const originalValue = this.#row.$original[name]; // if dirtyValue is null, check original type
|
|
292
|
-
const isDirtyAttachment = dirtyValue instanceof Attachment ||
|
|
293
|
-
(Array.isArray(dirtyValue) &&
|
|
294
|
-
dirtyValue.length &&
|
|
295
|
-
dirtyValue.every((item) => item instanceof Attachment));
|
|
296
|
-
const isOriginalAttachment = originalValue instanceof Attachment ||
|
|
297
|
-
(Array.isArray(originalValue) &&
|
|
298
|
-
originalValue.length &&
|
|
299
|
-
originalValue.every((item) => item instanceof Attachment));
|
|
300
|
-
return isDirtyAttachment || isOriginalAttachment;
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|