@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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import type { Attachment, Variant } from '../../types/attachment.js';
|
|
8
|
+
type PersistAttributes = {
|
|
9
|
+
id: string;
|
|
10
|
+
modelTable: string;
|
|
11
|
+
attributeName: string;
|
|
12
|
+
multiple: boolean;
|
|
13
|
+
};
|
|
14
|
+
export default class VariantPersisterService {
|
|
15
|
+
#private;
|
|
16
|
+
constructor({ id, modelTable, attributeName, multiple }: PersistAttributes);
|
|
17
|
+
persist({ attachments, variants }: {
|
|
18
|
+
attachments: Attachment[];
|
|
19
|
+
variants: Variant[];
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=variant_persister_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variant_persister_service.d.ts","sourceRoot":"","sources":["../../../../src/services/variant/variant_persister_service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAOpE,KAAK,iBAAiB,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,uBAAuB;;gBAM9B,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,iBAAiB;IAOpE,OAAO,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE;QACvC,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,QAAQ,EAAE,OAAO,EAAE,CAAA;KACpB,GAAG,OAAO,CAAC,IAAI,CAAC;CA2ClB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import logger from '@adonisjs/core/services/logger';
|
|
8
|
+
import string from '@adonisjs/core/helpers/string';
|
|
9
|
+
import db from '@adonisjs/lucid/services/db';
|
|
10
|
+
import attachmentManager from '../../../services/main.js';
|
|
11
|
+
export default class VariantPersisterService {
|
|
12
|
+
#id;
|
|
13
|
+
#modelTable;
|
|
14
|
+
#attributeName;
|
|
15
|
+
#multiple;
|
|
16
|
+
constructor({ id, modelTable, attributeName, multiple }) {
|
|
17
|
+
this.#id = id;
|
|
18
|
+
this.#modelTable = modelTable;
|
|
19
|
+
this.#attributeName = attributeName;
|
|
20
|
+
this.#multiple = multiple;
|
|
21
|
+
}
|
|
22
|
+
async persist({ attachments, variants }) {
|
|
23
|
+
const rollback = () => this.#rollbackVariants(variants);
|
|
24
|
+
const trx = await db.transaction();
|
|
25
|
+
trx.after('rollback', rollback);
|
|
26
|
+
try {
|
|
27
|
+
const data = this.#prepareUpdateData(attachments);
|
|
28
|
+
await this.#executeUpdate(trx, data);
|
|
29
|
+
await trx.commit();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
logger.error(`Persist failed: ${error.message}`);
|
|
33
|
+
await trx.rollback();
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
#rollbackVariants(variants) {
|
|
38
|
+
variants.forEach(variant => {
|
|
39
|
+
try {
|
|
40
|
+
attachmentManager.remove(variant);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
logger.error(`Rollback failed for variant: ${error.message}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
#prepareUpdateData(attachments) {
|
|
48
|
+
const index = string.snakeCase(this.#attributeName);
|
|
49
|
+
const data = this.#multiple
|
|
50
|
+
? attachments.map(att => att.toObject())
|
|
51
|
+
: attachments[0]?.toObject();
|
|
52
|
+
return { [index]: JSON.stringify(data) };
|
|
53
|
+
}
|
|
54
|
+
async #executeUpdate(trx, data) {
|
|
55
|
+
await trx.query()
|
|
56
|
+
.from(this.#modelTable)
|
|
57
|
+
.where('id', this.#id)
|
|
58
|
+
.update(data);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import type { Attachment } from '../../types/attachment.js';
|
|
8
|
+
export default class VariantPurger {
|
|
9
|
+
#private;
|
|
10
|
+
constructor(filters?: {
|
|
11
|
+
variants?: string[];
|
|
12
|
+
});
|
|
13
|
+
purge(attachments: Attachment[]): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=variant_purger_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variant_purger_service.d.ts","sourceRoot":"","sources":["../../../../src/services/variant/variant_purger_service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,2BAA2B,CAAA;AAIpE,MAAM,CAAC,OAAO,OAAO,aAAa;;gBAGpB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAIvC,KAAK,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA6CtD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import attachmentManager from '../../../services/main.js';
|
|
8
|
+
export default class VariantPurger {
|
|
9
|
+
#filters;
|
|
10
|
+
constructor(filters) {
|
|
11
|
+
this.#filters = filters;
|
|
12
|
+
}
|
|
13
|
+
async purge(attachments) {
|
|
14
|
+
const variantsToRemove = this.#getVariantsToRemove(attachments);
|
|
15
|
+
await Promise.all(variantsToRemove.map(variant => attachmentManager.remove(variant)));
|
|
16
|
+
this.#updateAttachmentVariants(attachments);
|
|
17
|
+
}
|
|
18
|
+
#getVariantsToRemove(attachments) {
|
|
19
|
+
const variants = [];
|
|
20
|
+
attachments.forEach(attachment => {
|
|
21
|
+
if (attachment.variants) {
|
|
22
|
+
attachment.variants.forEach(variant => {
|
|
23
|
+
if (this.#shouldRemoveVariant(variant)) {
|
|
24
|
+
variants.push(variant);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return variants;
|
|
30
|
+
}
|
|
31
|
+
#updateAttachmentVariants(attachments) {
|
|
32
|
+
attachments.forEach(attachment => {
|
|
33
|
+
if (attachment.variants) {
|
|
34
|
+
attachment.variants = this.#filterVariants(attachment.variants);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
#shouldRemoveVariant(variant) {
|
|
39
|
+
return this.#filters?.variants === undefined ||
|
|
40
|
+
this.#filters.variants.includes(variant.key);
|
|
41
|
+
}
|
|
42
|
+
#filterVariants(variants) {
|
|
43
|
+
if (this.#filters?.variants === undefined) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
return variants.filter(variant => !this.#filters.variants.includes(variant.key));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import type { ConverterInitializeAttributes } from '../types/converter.js';
|
|
8
|
+
export default class VariantService {
|
|
9
|
+
#private;
|
|
10
|
+
constructor({ record, attributeName, options, filters }: ConverterInitializeAttributes);
|
|
11
|
+
run(): Promise<import("../types/attachment.js").Variant[] | undefined>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=variant_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variant_service.d.ts","sourceRoot":"","sources":["../../../src/services/variant_service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAA;AAO1E,MAAM,CAAC,OAAO,OAAO,cAAc;;gBASrB,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,6BAA6B;IAgBhF,GAAG;CA6BV"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import logger from '@adonisjs/core/services/logger';
|
|
8
|
+
import VariantGeneratorService from './variant/variant_generator_service.js';
|
|
9
|
+
import VariantPurgerService from './variant/variant_purger_service.js';
|
|
10
|
+
import VariantPersisterService from './variant/variant_persister_service.js';
|
|
11
|
+
export default class VariantService {
|
|
12
|
+
#record;
|
|
13
|
+
#attributeName;
|
|
14
|
+
#options;
|
|
15
|
+
#filters;
|
|
16
|
+
#variantGenerator;
|
|
17
|
+
#variantPurger;
|
|
18
|
+
#variantPersister;
|
|
19
|
+
constructor({ record, attributeName, options, filters }) {
|
|
20
|
+
this.#record = record;
|
|
21
|
+
this.#attributeName = attributeName;
|
|
22
|
+
this.#options = options;
|
|
23
|
+
this.#filters = filters;
|
|
24
|
+
this.#variantGenerator = new VariantGeneratorService();
|
|
25
|
+
this.#variantPurger = new VariantPurgerService(filters);
|
|
26
|
+
this.#variantPersister = new VariantPersisterService({
|
|
27
|
+
id: record.row.$attributes['id'],
|
|
28
|
+
modelTable: record.row.constructor.table,
|
|
29
|
+
attributeName,
|
|
30
|
+
multiple: Array.isArray(record.row.$original[attributeName])
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async run() {
|
|
34
|
+
try {
|
|
35
|
+
const attachments = await this.#getAttachments();
|
|
36
|
+
if (!this.#shouldProcess(attachments)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await this.#variantPurger.purge(attachments);
|
|
40
|
+
const variants = await this.#variantGenerator.generate({ attachments, options: this.#options, filters: this.#filters });
|
|
41
|
+
await this.#variantPersister.persist({ attachments, variants });
|
|
42
|
+
return variants;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
logger.error(`VariantService.run failed: ${error.message}`);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async #getAttachments() {
|
|
50
|
+
// await this.#record.row.refresh()
|
|
51
|
+
return this.#record.getAttachments({
|
|
52
|
+
attributeName: this.#attributeName,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
#shouldProcess(attachments) {
|
|
56
|
+
return !!(attachments?.length && this.#options?.variants?.length);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -40,7 +40,7 @@ export type Attachment = AttachmentBase & {
|
|
|
40
40
|
originalName: string;
|
|
41
41
|
variants?: Variant[];
|
|
42
42
|
createVariant(key: string, input: Input): Promise<Variant>;
|
|
43
|
-
getVariant(variantName: string): Variant |
|
|
43
|
+
getVariant(variantName: string): Variant | null;
|
|
44
44
|
getUrl(variantName?: string): Promise<string>;
|
|
45
45
|
getSignedUrl(variantNameOrOptions?: string | SignedURLOptions, signedUrlOptions?: SignedURLOptions): Promise<string>;
|
|
46
46
|
toObject(): AttachmentAttributes;
|
|
@@ -52,9 +52,9 @@ export type Variant = AttachmentBase & {
|
|
|
52
52
|
generateBlurhash(options?: BlurhashOptions): void;
|
|
53
53
|
toObject(): VariantAttributes;
|
|
54
54
|
};
|
|
55
|
-
export type LucidOptions = {
|
|
55
|
+
export type LucidOptions<T = LucidRow> = {
|
|
56
56
|
disk?: string;
|
|
57
|
-
folder?: string | ((record
|
|
57
|
+
folder?: string | ((record: T) => string);
|
|
58
58
|
preComputeUrl?: boolean;
|
|
59
59
|
variants?: (keyof AttachmentVariants)[];
|
|
60
60
|
rename?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../../src/types/attachment.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,YAAY,CAAA;IAEnB,KAAK,CAAC,EAAE,KAAK,CAAA;IAEb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,OAAO,EAAE,YAAY,CAAA;IAErB,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACnC,OAAO,IAAI,IAAI,CAAA;IACf,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA;IAC/B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAC3C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IACzB,YAAY,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAElE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAA;IACvC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,cAAc,CAAA;IAEjD,QAAQ,IAAI,wBAAwB,CAAA;IACpC,MAAM,IAAI,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IAEpB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1D,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../../src/types/attachment.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,YAAY,CAAA;IAEnB,KAAK,CAAC,EAAE,KAAK,CAAA;IAEb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,OAAO,EAAE,YAAY,CAAA;IAErB,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACnC,OAAO,IAAI,IAAI,CAAA;IACf,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA;IAC/B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5B,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAC3C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IACzB,YAAY,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAElE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAA;IACvC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,cAAc,CAAA;IAEjD,QAAQ,IAAI,wBAAwB,CAAA;IACpC,MAAM,IAAI,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IAEpB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1D,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;IAC/C,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7C,YAAY,CACV,oBAAoB,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAChD,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,QAAQ,IAAI,oBAAoB,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG;IACrC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,gBAAgB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACjD,QAAQ,IAAI,iBAAiB,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,QAAQ,IAAI;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC,CAAA;IACzC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,CAAC,MAAM,kBAAkB,CAAC,EAAE,CAAA;IACvC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,OAAO,CAAA;IAC3C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,wBAAwB,GAAG;IAC5D,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC9B,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,wBAAwB,GAAG;IACzD,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA"}
|
package/build/src/types/index.js
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
7
|
+
import type { Verrou } from '@verrou/core';
|
|
8
|
+
import type { StoreFactory } from '@verrou/core/types';
|
|
9
|
+
interface LockStoresList {
|
|
10
|
+
}
|
|
11
|
+
export interface LockService extends Verrou<LockStoresList extends Record<string, StoreFactory> ? LockStoresList : never> {
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/types/lock.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,UAAU,cAAc;CAAG;AAE3B,MAAM,WAAW,WACf,SAAQ,MAAM,CAAC,cAAc,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,cAAc,GAAG,KAAK,CAAC;CAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/types/metadata.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/types/metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regenerate.d.ts","sourceRoot":"","sources":["../../../src/types/regenerate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,MAAM,kBAAkB,CAAC,EAAE,CAAA;CACxC,CAAA"}
|
|
1
|
+
{"version":3,"file":"regenerate.d.ts","sourceRoot":"","sources":["../../../src/types/regenerate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,MAAM,kBAAkB,CAAC,EAAE,CAAA;CACxC,CAAA"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jrmc/adonis-attachment
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
|
+
*/
|
|
1
7
|
import type { Attachment } from './attachment.js';
|
|
2
8
|
import type { RowWithAttachment } from './mixin.js';
|
|
3
9
|
export interface RecordWithAttachment {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/types/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,iBAAiB,CAAA;IACtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACvB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,WAAW,CAAC,OAAO,CAAC,EAAE;QAAE,eAAe,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,cAAc,CAAC,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,UAAU,EAAE,CAAA;CACtH"}
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/types/service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,iBAAiB,CAAA;IACtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACvB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,WAAW,CAAC,OAAO,CAAC,EAAE;QAAE,eAAe,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,cAAc,CAAC,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,UAAU,EAAE,CAAA;CACtH"}
|
package/build/src/utils/hooks.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
7
|
+
import AttachmentRecordService from '../services/attachment_service.js';
|
|
8
8
|
// @afterFind()
|
|
9
9
|
export const afterFindHook = async (instance) => {
|
|
10
10
|
const modelInstance = instance;
|
|
11
|
-
const model = new
|
|
11
|
+
const model = new AttachmentRecordService(modelInstance);
|
|
12
12
|
await model.setKeyId();
|
|
13
13
|
await model.preComputeUrl();
|
|
14
14
|
};
|
|
@@ -21,7 +21,7 @@ export const afterFetchHook = async (instance) => {
|
|
|
21
21
|
// @beforeSave()
|
|
22
22
|
export const beforeSaveHook = async (instance) => {
|
|
23
23
|
const modelInstance = instance;
|
|
24
|
-
const model = new
|
|
24
|
+
const model = new AttachmentRecordService(modelInstance);
|
|
25
25
|
await model.detach();
|
|
26
26
|
await model.persist();
|
|
27
27
|
await model.transaction();
|
|
@@ -29,13 +29,13 @@ export const beforeSaveHook = async (instance) => {
|
|
|
29
29
|
// @afterSave()
|
|
30
30
|
export const afterSaveHook = async (instance) => {
|
|
31
31
|
const modelInstance = instance;
|
|
32
|
-
const model = new
|
|
32
|
+
const model = new AttachmentRecordService(modelInstance);
|
|
33
33
|
await model.generateVariants();
|
|
34
34
|
};
|
|
35
35
|
// @beforeDelete()
|
|
36
36
|
export const beforeDeleteHook = async (instance) => {
|
|
37
37
|
const modelInstance = instance;
|
|
38
|
-
const model = new
|
|
38
|
+
const model = new AttachmentRecordService(modelInstance);
|
|
39
39
|
await model.detachAll();
|
|
40
40
|
await model.transaction({ enabledRollback: false });
|
|
41
41
|
};
|
package/build/stubs/config.stub
CHANGED
|
@@ -1,16 +1,114 @@
|
|
|
1
1
|
{{{
|
|
2
2
|
exports({ to: app.configPath('attachment.ts') })
|
|
3
3
|
}}}
|
|
4
|
+
// import sharp from 'sharp'
|
|
4
5
|
import { defineConfig } from '@jrmc/adonis-attachment'
|
|
5
6
|
import { InferConverters } from '@jrmc/adonis-attachment/types/config'
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Documentation: https://adonis-attachment.jrmc.dev/guide/essentials/configuration
|
|
10
|
+
*/
|
|
11
|
+
|
|
7
12
|
const attachmentConfig = defineConfig({
|
|
13
|
+
/**
|
|
14
|
+
* Enable the preComputeUrl flag to pre compute the URLs after SELECT queries. (default: false)
|
|
15
|
+
*/
|
|
16
|
+
// preComputeUrl: true,
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Enable the meta informations after upload. (default: false)
|
|
20
|
+
*/
|
|
21
|
+
// meta: true,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Enable file rename after upload. (default: true)
|
|
25
|
+
*/
|
|
26
|
+
// rename: false,
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Specify binary path
|
|
30
|
+
*/
|
|
31
|
+
// bin: { // [!code focus:8]
|
|
32
|
+
// ffmpegPath: 'ffmpeg_path', // the full path of the binary
|
|
33
|
+
// ffprobePath: 'ffprobe_path', // the full path of the binary
|
|
34
|
+
// pdftoppmPath: 'pdftoppm_path' // the full path of the binary
|
|
35
|
+
// pdfinfoPath: 'pdfinfo_path' // the full path of the binary
|
|
36
|
+
// sofficePath: 'soffice_path', // the full path of the binary (libreoffice/openoffice)
|
|
37
|
+
// },
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Queue configuration for file processing.
|
|
41
|
+
* By default, 1 task is processed concurrently. A task corresponds to a model attribute.
|
|
42
|
+
* For example, if a model has a logo attribute and an avatar attribute,
|
|
43
|
+
* this represents 2 tasks, regardless of the number of concerts per attribute.
|
|
44
|
+
*
|
|
45
|
+
* Increasing concurrency can improve performance but consumes more resources.
|
|
46
|
+
* A value too high may lead to memory or CPU issues.
|
|
47
|
+
*
|
|
48
|
+
*/
|
|
49
|
+
// queue: {
|
|
50
|
+
// concurrency: 2
|
|
51
|
+
// },
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Maximum duration (in milliseconds) that an operation can take before being interrupted.
|
|
55
|
+
* Default: 30_000 (30 seconds)
|
|
56
|
+
*
|
|
57
|
+
* This timeout applies to each individual operation conversion.
|
|
58
|
+
* If an operation exceeds this time limit, it will be interrupted and an error will be thrown.
|
|
59
|
+
*
|
|
60
|
+
* Increase this value if you're processing large files or if your operations
|
|
61
|
+
* require more time (e.g., long video conversion).
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
// timeout: 40_000,
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
*
|
|
68
|
+
*/
|
|
8
69
|
converters: {
|
|
9
70
|
thumbnail: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
71
|
+
/**
|
|
72
|
+
* optional converter
|
|
73
|
+
* default : @jrmc/adonis-attachment/converters/autodetect_converter
|
|
74
|
+
* image : @jrmc/adonis-attachment/converters/image_converter
|
|
75
|
+
* pdf : @jrmc/adonis-attachment/converters/pdf_thumbnail_converter
|
|
76
|
+
* document : @jrmc/adonis-attachment/converters/document_thumbnail_converter
|
|
77
|
+
* video : @jrmc/adonis-attachment/converters/video_thumbnail_converter
|
|
78
|
+
* create your custom converter : https://adonis-attachment.jrmc.dev/guide/advanced_usage/custom-converter
|
|
79
|
+
*/
|
|
80
|
+
// converter: () => import('@jrmc/adonis-attachment/converters/autodetect_converter'),
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* https://sharp.pixelplumbing.com/api-resize/
|
|
85
|
+
*/
|
|
86
|
+
resize: 300,
|
|
87
|
+
|
|
88
|
+
// resize: { // https://sharp.pixelplumbing.com/api-resize
|
|
89
|
+
// width: 400,
|
|
90
|
+
// height: 400,
|
|
91
|
+
// fit: sharp.fit.cover,
|
|
92
|
+
// position: 'top'
|
|
93
|
+
// },
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* https://sharp.pixelplumbing.com/api-output/#toformat
|
|
98
|
+
*/
|
|
99
|
+
// format: 'jpeg',
|
|
100
|
+
// format: {
|
|
101
|
+
// format: 'jpeg',
|
|
102
|
+
// options: {
|
|
103
|
+
// quality: 80
|
|
104
|
+
// }
|
|
105
|
+
// }
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* generation of blurhashes (default: true)
|
|
109
|
+
* https://blurha.sh/
|
|
110
|
+
*/
|
|
111
|
+
// blurhash: true
|
|
14
112
|
}
|
|
15
113
|
}
|
|
16
114
|
})
|