@jrmc/adonis-attachment 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,9 +5,9 @@
5
5
  * @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
6
6
  */
7
7
  import type { LoggerService } from '@adonisjs/core/types';
8
- import type { DriveService } from '@adonisjs/drive/types';
8
+ import type { DriveService, SignedURLOptions } from '@adonisjs/drive/types';
9
9
  import type { MultipartFile } from '@adonisjs/core/bodyparser';
10
- import type { AttachmentBase } from './types/attachment.js';
10
+ import type { AttachmentBase, Attachment as AttachmentType } from './types/attachment.js';
11
11
  import type { ResolvedAttachmentConfig } from './types/config.js';
12
12
  import { Attachment } from './attachments/attachment.js';
13
13
  import Converter from './converters/converter.js';
@@ -19,6 +19,8 @@ export declare class AttachmentManager {
19
19
  createFromFile(file: MultipartFile): Promise<Attachment>;
20
20
  createFromBuffer(buffer: Buffer, name?: string): Promise<Attachment>;
21
21
  getConverter(key: string): Promise<void | Converter>;
22
+ computeUrl(attachment: AttachmentType | AttachmentBase, signedUrlOptions?: SignedURLOptions): Promise<void>;
23
+ preComputeUrl(attachment: AttachmentType): Promise<void>;
22
24
  save(attachment: AttachmentBase): Promise<void>;
23
25
  delete(attachment: AttachmentBase): Promise<void>;
24
26
  }
@@ -58,6 +58,29 @@ export class AttachmentManager {
58
58
  }
59
59
  }
60
60
  }
61
+ async computeUrl(attachment, signedUrlOptions) {
62
+ const disk = attachment.getDisk();
63
+ const fileVisibility = await disk.getVisibility(attachment.path);
64
+ if (fileVisibility === 'private') {
65
+ attachment.url = await attachment.getSignedUrl(signedUrlOptions);
66
+ }
67
+ else {
68
+ attachment.url = await attachment.getUrl();
69
+ }
70
+ }
71
+ async preComputeUrl(attachment) {
72
+ if (attachment.options?.preComputeUrl === false) {
73
+ return;
74
+ }
75
+ await this.computeUrl(attachment);
76
+ if (attachment instanceof Attachment && attachment.variants) {
77
+ for (const key in attachment.variants) {
78
+ if (Object.prototype.hasOwnProperty.call(attachment.variants, key)) {
79
+ await this.computeUrl(attachment.variants[key]);
80
+ }
81
+ }
82
+ }
83
+ }
61
84
  async save(attachment) {
62
85
  const destinationPath = attachment.path;
63
86
  if (attachment.options?.meta) {
@@ -19,5 +19,5 @@ export declare class Attachment extends AttachmentBase implements AttachmentInte
19
19
  getSignedUrl(variantNameOrOptions?: string | SignedURLOptions, signedUrlOptions?: SignedURLOptions): Promise<string>;
20
20
  setOptions(options: LucidOptions): this;
21
21
  toObject(): AttachmentAttributes;
22
- toJSON(): Promise<Object>;
22
+ toJSON(): Object;
23
23
  }
@@ -79,6 +79,14 @@ export class Attachment extends AttachmentBase {
79
79
  this.folder = this.options.folder;
80
80
  this.path = path.join(this.folder, this.name);
81
81
  }
82
+ if (this.variants) {
83
+ this.variants.forEach((v) => {
84
+ v.setOptions({
85
+ ...this.options,
86
+ variants: []
87
+ });
88
+ });
89
+ }
82
90
  return this;
83
91
  }
84
92
  toObject() {
@@ -89,7 +97,7 @@ export class Attachment extends AttachmentBase {
89
97
  variants,
90
98
  };
91
99
  }
92
- async toJSON() {
100
+ toJSON() {
93
101
  const data = {
94
102
  name: this.name,
95
103
  originalName: this.originalName,
@@ -97,16 +105,27 @@ export class Attachment extends AttachmentBase {
97
105
  extname: this.extname,
98
106
  mimetype: this.mimeType,
99
107
  meta: this.meta,
100
- url: await this.getUrl(),
101
- signedUrl: await this.getSignedUrl(),
102
108
  };
103
109
  if (this.variants) {
104
- await Promise.allSettled(this.variants.map(async (v) => {
110
+ this.variants.map(async (v) => {
105
111
  data[v.key] = {
106
- url: await this.getUrl(v.key),
107
- signedUrl: await this.getSignedUrl(v.key)
112
+ name: v.name,
113
+ extname: v.extname,
114
+ mimetype: v.mimeType,
115
+ meta: v.meta,
116
+ size: v.size,
108
117
  };
109
- }));
118
+ });
119
+ }
120
+ if (this.url) {
121
+ data.url = this.url;
122
+ }
123
+ if (this.variants) {
124
+ this.variants.map(async (v) => {
125
+ if (v.url) {
126
+ data[v.key].url = v.url;
127
+ }
128
+ });
110
129
  }
111
130
  return data;
112
131
  }
@@ -17,6 +17,7 @@ export declare class AttachmentBase implements AttachmentBaseInterface {
17
17
  meta?: Exif;
18
18
  folder?: string;
19
19
  path?: string;
20
+ url?: string;
20
21
  options?: LucidOptions;
21
22
  constructor(drive: DriveService, attributes: AttachmentBaseAttributes, input?: Input);
22
23
  getDisk(): import("flydrive").Disk;
@@ -24,5 +25,5 @@ export declare class AttachmentBase implements AttachmentBaseInterface {
24
25
  getSignedUrl(signedUrlOptions?: SignedURLOptions): Promise<string>;
25
26
  setOptions(options: LucidOptions): this;
26
27
  toObject(): AttachmentBaseAttributes;
27
- toJSON(): Promise<Object>;
28
+ toJSON(): Object;
28
29
  }
@@ -16,6 +16,7 @@ export class AttachmentBase {
16
16
  meta;
17
17
  folder;
18
18
  path;
19
+ url;
19
20
  options;
20
21
  constructor(drive, attributes, input) {
21
22
  this.input = input;
@@ -60,11 +61,13 @@ export class AttachmentBase {
60
61
  path: this.path,
61
62
  };
62
63
  }
63
- async toJSON() {
64
- return {
65
- ...this.toObject(),
66
- url: await this.getUrl(),
67
- signedUrl: await this.getSignedUrl(),
68
- };
64
+ toJSON() {
65
+ if (this.url) {
66
+ return {
67
+ ...this.toObject(),
68
+ url: this.url
69
+ };
70
+ }
71
+ return this.toObject();
69
72
  }
70
73
  }
@@ -16,6 +16,7 @@ export const attachment = (options) => {
16
16
  const defaultOptions = {
17
17
  meta: defaultConfig.meta !== undefined ? defaultConfig.meta : defaultOptionsDecorator.meta,
18
18
  rename: defaultConfig.rename !== undefined ? defaultConfig.rename : defaultOptionsDecorator.rename,
19
+ preComputeUrl: defaultConfig.preComputeUrl !== undefined ? defaultConfig.preComputeUrl : defaultOptionsDecorator.preComputeUrl,
19
20
  };
20
21
  if (!options || options?.meta === undefined) {
21
22
  options.meta = defaultOptions.meta;
@@ -23,6 +24,9 @@ export const attachment = (options) => {
23
24
  if (!options || options?.rename === undefined) {
24
25
  options.rename = defaultOptions.rename;
25
26
  }
27
+ if (!options || options?.preComputeUrl === undefined) {
28
+ options.preComputeUrl = defaultOptions.preComputeUrl;
29
+ }
26
30
  target[optionsSym][attributeName] = options;
27
31
  const Model = target.constructor;
28
32
  Model.boot();
@@ -42,7 +46,7 @@ export const attachment = (options) => {
42
46
  }
43
47
  },
44
48
  prepare: (value) => (value ? JSON.stringify(value.toObject()) : null),
45
- serialize: async (value) => (value ? await value.toJSON() : null),
49
+ serialize: (value) => (value ? value.toJSON() : null),
46
50
  ...columnOptions,
47
51
  });
48
52
  };
@@ -68,6 +68,126 @@ export declare const Attachmentable: <Model extends NormalizeConstructor<typeof
68
68
  toJSON(): import("@adonisjs/lucid/types/model").ModelObject;
69
69
  related<Name_2 extends undefined>(relation: Name_2): any[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? any[Name_2]["client"] : never;
70
70
  };
71
+ afterFindHook(modelInstance: {
72
+ $attachments: AttributeOfModelWithAttachment;
73
+ $attributes: import("@adonisjs/lucid/types/model").ModelObject;
74
+ $extras: import("@adonisjs/lucid/types/model").ModelObject;
75
+ $original: import("@adonisjs/lucid/types/model").ModelObject;
76
+ $preloaded: {
77
+ [relation: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
78
+ };
79
+ $columns: undefined;
80
+ $sideloaded: import("@adonisjs/lucid/types/model").ModelObject;
81
+ $primaryKeyValue?: number | string;
82
+ $isPersisted: boolean;
83
+ $isNew: boolean;
84
+ $isLocal: boolean;
85
+ $dirty: import("@adonisjs/lucid/types/model").ModelObject;
86
+ $isDirty: boolean;
87
+ $isDeleted: boolean;
88
+ $options?: import("@adonisjs/lucid/types/model").ModelOptions;
89
+ $trx?: import("@adonisjs/lucid/types/database").TransactionClientContract;
90
+ $setOptionsAndTrx(options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): void;
91
+ useTransaction(trx: import("@adonisjs/lucid/types/database").TransactionClientContract): any;
92
+ useConnection(connection: string): any;
93
+ $getQueryFor(action: "insert", client: import("@adonisjs/lucid/types/database").QueryClientContract): ReturnType<import("@adonisjs/lucid/types/database").QueryClientContract["insertQuery"]>;
94
+ $getQueryFor(action: "update" | "delete" | "refresh", client: import("@adonisjs/lucid/types/database").QueryClientContract): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel>;
95
+ $setAttribute(key: string, value: any): void;
96
+ $getAttribute(key: string): any;
97
+ $getAttributeFromCache(key: string, callback: import("@adonisjs/lucid/types/model").CacheNode["getter"]): any;
98
+ $hasRelated(key: string): boolean;
99
+ $setRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
100
+ $pushRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
101
+ $getRelated(key: string, defaultValue?: any): import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | undefined | null;
102
+ $consumeAdapterResult(adapterResult: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject): void;
103
+ $hydrateOriginals(): void;
104
+ fill(value: Partial<{
105
+ $attachments: AttributeOfModelWithAttachment;
106
+ }>, allowExtraProperties?: boolean): any;
107
+ merge(value: Partial<{
108
+ $attachments: AttributeOfModelWithAttachment;
109
+ }>, allowExtraProperties?: boolean): any;
110
+ enableForceUpdate(): any;
111
+ save(): Promise<any>;
112
+ lockForUpdate<T>(callback: (user: any) => T | Promise<T>): Promise<T>;
113
+ delete(): Promise<void>;
114
+ refresh(): Promise<any>;
115
+ load: import("@adonisjs/lucid/types/model").LucidRowPreload<any>;
116
+ preload: import("@adonisjs/lucid/types/model").LucidRowPreload<any>;
117
+ loadAggregate: <Self extends any, Name extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? Self[Name]["subQuery"] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
118
+ loadCount: <Self extends any, Name_1 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder_1 = Self[Name_1] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? Self[Name_1]["subQuery"] : never>(name: Name_1, callback?: ((builder: RelatedBuilder_1) => void) | undefined) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
119
+ serializeAttributes(fields?: import("@adonisjs/lucid/types/model").CherryPickFields, raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
120
+ serializeComputed(fields?: import("@adonisjs/lucid/types/model").CherryPickFields): import("@adonisjs/lucid/types/model").ModelObject;
121
+ serializeRelations(fields: undefined, raw: true): {
122
+ [key: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
123
+ };
124
+ serializeRelations(cherryPick: import("@adonisjs/lucid/types/model").CherryPick["relations"] | undefined, raw: false | undefined): import("@adonisjs/lucid/types/model").ModelObject;
125
+ serializeRelations(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick["relations"], raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
126
+ serialize(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick): import("@adonisjs/lucid/types/model").ModelObject;
127
+ toObject(): import("@adonisjs/lucid/types/model").ModelObject;
128
+ toJSON(): import("@adonisjs/lucid/types/model").ModelObject;
129
+ related<Name_2 extends undefined>(relation: Name_2): any[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? any[Name_2]["client"] : never;
130
+ }): Promise<void>;
131
+ afterFetchHook(modelInstances: {
132
+ $attachments: AttributeOfModelWithAttachment;
133
+ $attributes: import("@adonisjs/lucid/types/model").ModelObject;
134
+ $extras: import("@adonisjs/lucid/types/model").ModelObject;
135
+ $original: import("@adonisjs/lucid/types/model").ModelObject;
136
+ $preloaded: {
137
+ [relation: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
138
+ };
139
+ $columns: undefined;
140
+ $sideloaded: import("@adonisjs/lucid/types/model").ModelObject;
141
+ $primaryKeyValue?: number | string;
142
+ $isPersisted: boolean;
143
+ $isNew: boolean;
144
+ $isLocal: boolean;
145
+ $dirty: import("@adonisjs/lucid/types/model").ModelObject;
146
+ $isDirty: boolean;
147
+ $isDeleted: boolean;
148
+ $options?: import("@adonisjs/lucid/types/model").ModelOptions;
149
+ $trx?: import("@adonisjs/lucid/types/database").TransactionClientContract;
150
+ $setOptionsAndTrx(options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): void;
151
+ useTransaction(trx: import("@adonisjs/lucid/types/database").TransactionClientContract): any;
152
+ useConnection(connection: string): any;
153
+ $getQueryFor(action: "insert", client: import("@adonisjs/lucid/types/database").QueryClientContract): ReturnType<import("@adonisjs/lucid/types/database").QueryClientContract["insertQuery"]>;
154
+ $getQueryFor(action: "update" | "delete" | "refresh", client: import("@adonisjs/lucid/types/database").QueryClientContract): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel>;
155
+ $setAttribute(key: string, value: any): void;
156
+ $getAttribute(key: string): any;
157
+ $getAttributeFromCache(key: string, callback: import("@adonisjs/lucid/types/model").CacheNode["getter"]): any;
158
+ $hasRelated(key: string): boolean;
159
+ $setRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
160
+ $pushRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
161
+ $getRelated(key: string, defaultValue?: any): import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | undefined | null;
162
+ $consumeAdapterResult(adapterResult: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject): void;
163
+ $hydrateOriginals(): void;
164
+ fill(value: Partial<{
165
+ $attachments: AttributeOfModelWithAttachment;
166
+ }>, allowExtraProperties?: boolean): any;
167
+ merge(value: Partial<{
168
+ $attachments: AttributeOfModelWithAttachment;
169
+ }>, allowExtraProperties?: boolean): any;
170
+ enableForceUpdate(): any;
171
+ save(): Promise<any>;
172
+ lockForUpdate<T>(callback: (user: any) => T | Promise<T>): Promise<T>;
173
+ delete(): Promise<void>;
174
+ refresh(): Promise<any>;
175
+ load: import("@adonisjs/lucid/types/model").LucidRowPreload<any>;
176
+ preload: import("@adonisjs/lucid/types/model").LucidRowPreload<any>;
177
+ loadAggregate: <Self extends any, Name extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? Self[Name]["subQuery"] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
178
+ loadCount: <Self extends any, Name_1 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder_1 = Self[Name_1] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? Self[Name_1]["subQuery"] : never>(name: Name_1, callback?: ((builder: RelatedBuilder_1) => void) | undefined) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
179
+ serializeAttributes(fields?: import("@adonisjs/lucid/types/model").CherryPickFields, raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
180
+ serializeComputed(fields?: import("@adonisjs/lucid/types/model").CherryPickFields): import("@adonisjs/lucid/types/model").ModelObject;
181
+ serializeRelations(fields: undefined, raw: true): {
182
+ [key: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
183
+ };
184
+ serializeRelations(cherryPick: import("@adonisjs/lucid/types/model").CherryPick["relations"] | undefined, raw: false | undefined): import("@adonisjs/lucid/types/model").ModelObject;
185
+ serializeRelations(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick["relations"], raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
186
+ serialize(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick): import("@adonisjs/lucid/types/model").ModelObject;
187
+ toObject(): import("@adonisjs/lucid/types/model").ModelObject;
188
+ toJSON(): import("@adonisjs/lucid/types/model").ModelObject;
189
+ related<Name_2 extends undefined>(relation: Name_2): any[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? any[Name_2]["client"] : never;
190
+ }[]): Promise<void>;
71
191
  beforeSaveHook(modelInstance: {
72
192
  $attachments: AttributeOfModelWithAttachment;
73
193
  $attributes: import("@adonisjs/lucid/types/model").ModelObject;
@@ -10,13 +10,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
10
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
11
  return c > 3 && r && Object.defineProperty(target, key, r), r;
12
12
  };
13
- import { beforeSave, afterSave, beforeDelete } from '@adonisjs/lucid/orm';
14
- import { persistAttachment, commit, rollback, generateVariants } from '../utils/actions.js';
13
+ import { beforeSave, afterSave, beforeDelete, afterFind, afterFetch, afterPaginate } from '@adonisjs/lucid/orm';
14
+ import { persistAttachment, commit, rollback, generateVariants, preComputeUrl } from '../utils/actions.js';
15
15
  import { clone, getAttachmentAttributeNames } from '../utils/helpers.js';
16
16
  import { defaultStateAttributeMixin } from '../utils/default_values.js';
17
17
  export const Attachmentable = (superclass) => {
18
18
  class ModelWithAttachment extends superclass {
19
19
  $attachments = clone(defaultStateAttributeMixin);
20
+ static async afterFindHook(modelInstance) {
21
+ const attachmentAttributeNames = getAttachmentAttributeNames(modelInstance);
22
+ await Promise.all(attachmentAttributeNames.map((attributeName) => {
23
+ return preComputeUrl(modelInstance, attributeName);
24
+ }));
25
+ }
26
+ static async afterFetchHook(modelInstances) {
27
+ await Promise.all(modelInstances.map((row) => this.afterFindHook(row)));
28
+ }
20
29
  static async beforeSaveHook(modelInstance) {
21
30
  const attachmentAttributeNames = getAttachmentAttributeNames(modelInstance);
22
31
  /**
@@ -85,6 +94,13 @@ export const Attachmentable = (superclass) => {
85
94
  }
86
95
  }
87
96
  }
97
+ __decorate([
98
+ afterFind()
99
+ ], ModelWithAttachment, "afterFindHook", null);
100
+ __decorate([
101
+ afterFetch(),
102
+ afterPaginate()
103
+ ], ModelWithAttachment, "afterFetchHook", null);
88
104
  __decorate([
89
105
  beforeSave()
90
106
  ], ModelWithAttachment, "beforeSaveHook", null);
@@ -18,13 +18,14 @@ export type AttachmentBase = {
18
18
  meta?: Exif;
19
19
  folder?: string;
20
20
  path?: string;
21
+ url?: string;
21
22
  options?: LucidOptions;
22
23
  getDisk(): Disk;
23
24
  getUrl(): Promise<string>;
24
25
  getSignedUrl(signedUrlOptions?: SignedURLOptions): Promise<string>;
25
26
  setOptions(options: LucidOptions): AttachmentBase;
26
27
  toObject(): AttachmentBaseAttributes;
27
- toJSON(): Promise<Object>;
28
+ toJSON(): Object;
28
29
  };
29
30
  export type Attachment = AttachmentBase & {
30
31
  originalName: string;
@@ -43,6 +44,7 @@ export type Variant = AttachmentBase & {
43
44
  export type LucidOptions = {
44
45
  disk?: string;
45
46
  folder?: string;
47
+ preComputeUrl?: boolean;
46
48
  variants?: string[];
47
49
  rename?: boolean;
48
50
  meta?: boolean;
@@ -21,6 +21,7 @@ export type AttachmentConfig = {
21
21
  bin?: BinPaths;
22
22
  meta?: boolean;
23
23
  rename?: boolean;
24
+ preComputeUrl?: boolean;
24
25
  converters?: ConverterConfig[];
25
26
  };
26
27
  export type ResolvedConverter = {
@@ -31,6 +32,7 @@ export type ResolvedAttachmentConfig = {
31
32
  bin?: BinPaths;
32
33
  meta?: boolean;
33
34
  rename?: boolean;
35
+ preComputeUrl?: boolean;
34
36
  converters?: ResolvedConverter[];
35
37
  };
36
38
  export {};
@@ -14,9 +14,10 @@ export declare function commit(modelInstance: ModelWithAttachment): Promise<void
14
14
  */
15
15
  export declare function rollback(modelInstance: ModelWithAttachment): Promise<void>;
16
16
  /**
17
- * Persist attachment for a given attachment property
17
+ * Persist attachment for a given attachment attributeName
18
18
  */
19
- export declare function persistAttachment(modelInstance: ModelWithAttachment, property: string): Promise<void>;
19
+ export declare function persistAttachment(modelInstance: ModelWithAttachment, attributeName: string): Promise<void>;
20
+ export declare function preComputeUrl(modelInstance: ModelWithAttachment, attributeName: string): Promise<void>;
20
21
  /**
21
22
  * Launch converter by variant option
22
23
  */
@@ -20,14 +20,14 @@ export async function rollback(modelInstance) {
20
20
  await Promise.allSettled(modelInstance.$attachments.attached.map((attachment) => attachmentManager.delete(attachment)));
21
21
  }
22
22
  /**
23
- * Persist attachment for a given attachment property
23
+ * Persist attachment for a given attachment attributeName
24
24
  */
25
- export async function persistAttachment(modelInstance, property) {
26
- const existingFile = modelInstance.$original[property];
27
- const newFile = modelInstance.$attributes[property];
28
- const options = getOptions(modelInstance, property);
25
+ export async function persistAttachment(modelInstance, attributeName) {
26
+ const existingFile = modelInstance.$original[attributeName];
27
+ const newFile = modelInstance.$attributes[attributeName];
28
+ const options = getOptions(modelInstance, attributeName);
29
29
  /**
30
- * Skip when the attachment property hasn't been updated
30
+ * Skip when the attachment attributeName hasn't been updated
31
31
  */
32
32
  if (existingFile === newFile) {
33
33
  return;
@@ -62,6 +62,12 @@ export async function persistAttachment(modelInstance, property) {
62
62
  await attachmentManager.save(newFile);
63
63
  }
64
64
  }
65
+ export async function preComputeUrl(modelInstance, attributeName) {
66
+ const attachment = modelInstance.$attributes[attributeName];
67
+ const options = getOptions(modelInstance, attributeName);
68
+ attachment.setOptions(options);
69
+ return attachmentManager.preComputeUrl(attachment);
70
+ }
65
71
  /**
66
72
  * Launch converter by variant option
67
73
  */
@@ -7,9 +7,10 @@
7
7
  export declare const defaultOptionsDecorator: {
8
8
  disk: undefined;
9
9
  folder: string;
10
+ preComputeUrl: boolean;
10
11
  variants: never[];
11
- rename: boolean;
12
12
  meta: boolean;
13
+ rename: boolean;
13
14
  };
14
15
  export declare const defaultStateAttributeMixin: {
15
16
  attached: never[];
@@ -7,9 +7,10 @@
7
7
  export const defaultOptionsDecorator = {
8
8
  disk: undefined,
9
9
  folder: 'uploads',
10
+ preComputeUrl: false,
10
11
  variants: [],
11
- rename: true,
12
- meta: true
12
+ meta: true,
13
+ rename: true
13
14
  };
14
15
  export const defaultStateAttributeMixin = {
15
16
  attached: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrmc/adonis-attachment",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "description": "Turn any field on your Lucid model to an attachment data type",
6
6
  "engines": {