@bgord/bun 1.18.16 → 1.19.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.
- package/dist/{image-blur-sharp.adapter.d.ts → image-blur.adapter.d.ts} +5 -9
- package/dist/image-blur.adapter.d.ts.map +1 -0
- package/dist/image-blur.adapter.js +19 -0
- package/dist/image-blur.adapter.js.map +1 -0
- package/dist/image-blur.port.d.ts +0 -2
- package/dist/image-blur.port.d.ts.map +1 -1
- package/dist/{image-compressor-sharp.adapter.d.ts → image-compressor.adapter.d.ts} +5 -9
- package/dist/image-compressor.adapter.d.ts.map +1 -0
- package/dist/image-compressor.adapter.js +20 -0
- package/dist/image-compressor.adapter.js.map +1 -0
- package/dist/image-exif-clear.adapter.d.ts +15 -0
- package/dist/image-exif-clear.adapter.d.ts.map +1 -0
- package/dist/image-exif-clear.adapter.js +17 -0
- package/dist/image-exif-clear.adapter.js.map +1 -0
- package/dist/{image-formatter-sharp.adapter.d.ts → image-formatter.adapter.d.ts} +5 -9
- package/dist/image-formatter.adapter.d.ts.map +1 -0
- package/dist/image-formatter.adapter.js +22 -0
- package/dist/image-formatter.adapter.js.map +1 -0
- package/dist/{image-grayscale-sharp.adapter.d.ts → image-grayscale.adapter.d.ts} +5 -9
- package/dist/image-grayscale.adapter.d.ts.map +1 -0
- package/dist/image-grayscale.adapter.js +22 -0
- package/dist/image-grayscale.adapter.js.map +1 -0
- package/dist/image-info.adapter.d.ts +12 -0
- package/dist/image-info.adapter.d.ts.map +1 -0
- package/dist/image-info.adapter.js +21 -0
- package/dist/image-info.adapter.js.map +1 -0
- package/dist/{image-processor-sharp.adapter.d.ts → image-processor.adapter.d.ts} +5 -9
- package/dist/image-processor.adapter.d.ts.map +1 -0
- package/dist/image-processor.adapter.js +28 -0
- package/dist/image-processor.adapter.js.map +1 -0
- package/dist/image-processor.port.d.ts +0 -8
- package/dist/image-processor.port.d.ts.map +1 -1
- package/dist/{image-resizer-sharp.adapter.d.ts → image-resizer.adapter.d.ts} +5 -9
- package/dist/image-resizer.adapter.d.ts.map +1 -0
- package/dist/image-resizer.adapter.js +21 -0
- package/dist/image-resizer.adapter.js.map +1 -0
- package/dist/image.types.d.ts +2 -0
- package/dist/image.types.d.ts.map +1 -0
- package/dist/image.types.js +2 -0
- package/dist/image.types.js.map +1 -0
- package/dist/index.d.ts +9 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -12
- package/dist/index.js.map +1 -1
- package/dist/mailer-file.adapter.d.ts.map +1 -1
- package/dist/mailer-file.adapter.js +1 -0
- package/dist/mailer-file.adapter.js.map +1 -1
- package/dist/request-context-hono.adapter.d.ts.map +1 -1
- package/dist/request-context-hono.adapter.js +1 -0
- package/dist/request-context-hono.adapter.js.map +1 -1
- package/package.json +1 -6
- package/readme.md +9 -12
- package/src/image-blur.adapter.ts +29 -0
- package/src/image-blur.port.ts +0 -2
- package/src/image-compressor.adapter.ts +31 -0
- package/src/image-exif-clear.adapter.ts +26 -0
- package/src/image-formatter.adapter.ts +39 -0
- package/src/image-grayscale.adapter.ts +33 -0
- package/src/image-info.adapter.ts +26 -0
- package/src/image-processor.adapter.ts +46 -0
- package/src/image-processor.port.ts +0 -3
- package/src/image-resizer.adapter.ts +31 -0
- package/src/image.types.ts +1 -0
- package/src/index.ts +9 -12
- package/src/mailer-file.adapter.ts +1 -0
- package/src/request-context-hono.adapter.ts +1 -0
- package/dist/image-alpha-noop.adapter.d.ts +0 -6
- package/dist/image-alpha-noop.adapter.d.ts.map +0 -1
- package/dist/image-alpha-noop.adapter.js +0 -6
- package/dist/image-alpha-noop.adapter.js.map +0 -1
- package/dist/image-alpha-sharp.adapter.d.ts +0 -19
- package/dist/image-alpha-sharp.adapter.d.ts.map +0 -1
- package/dist/image-alpha-sharp.adapter.js +0 -96
- package/dist/image-alpha-sharp.adapter.js.map +0 -1
- package/dist/image-alpha-with-semaphore.adapter.d.ts +0 -14
- package/dist/image-alpha-with-semaphore.adapter.d.ts.map +0 -1
- package/dist/image-alpha-with-semaphore.adapter.js +0 -10
- package/dist/image-alpha-with-semaphore.adapter.js.map +0 -1
- package/dist/image-alpha.port.d.ts +0 -24
- package/dist/image-alpha.port.d.ts.map +0 -1
- package/dist/image-alpha.port.js +0 -2
- package/dist/image-alpha.port.js.map +0 -1
- package/dist/image-blur-sharp.adapter.d.ts.map +0 -1
- package/dist/image-blur-sharp.adapter.js +0 -92
- package/dist/image-blur-sharp.adapter.js.map +0 -1
- package/dist/image-compressor-sharp.adapter.d.ts.map +0 -1
- package/dist/image-compressor-sharp.adapter.js +0 -94
- package/dist/image-compressor-sharp.adapter.js.map +0 -1
- package/dist/image-exif-clear-sharp.adapter.d.ts +0 -19
- package/dist/image-exif-clear-sharp.adapter.d.ts.map +0 -1
- package/dist/image-exif-clear-sharp.adapter.js +0 -90
- package/dist/image-exif-clear-sharp.adapter.js.map +0 -1
- package/dist/image-formatter-sharp.adapter.d.ts.map +0 -1
- package/dist/image-formatter-sharp.adapter.js +0 -96
- package/dist/image-formatter-sharp.adapter.js.map +0 -1
- package/dist/image-grayscale-sharp.adapter.d.ts.map +0 -1
- package/dist/image-grayscale-sharp.adapter.js +0 -90
- package/dist/image-grayscale-sharp.adapter.js.map +0 -1
- package/dist/image-info-sharp.adapter.d.ts +0 -20
- package/dist/image-info-sharp.adapter.d.ts.map +0 -1
- package/dist/image-info-sharp.adapter.js +0 -95
- package/dist/image-info-sharp.adapter.js.map +0 -1
- package/dist/image-processor-sharp.adapter.d.ts.map +0 -1
- package/dist/image-processor-sharp.adapter.js +0 -109
- package/dist/image-processor-sharp.adapter.js.map +0 -1
- package/dist/image-resizer-sharp.adapter.d.ts.map +0 -1
- package/dist/image-resizer-sharp.adapter.js +0 -101
- package/dist/image-resizer-sharp.adapter.js.map +0 -1
- package/src/image-alpha-noop.adapter.ts +0 -8
- package/src/image-alpha-sharp.adapter.ts +0 -53
- package/src/image-alpha-with-semaphore.adapter.ts +0 -13
- package/src/image-alpha.port.ts +0 -19
- package/src/image-blur-sharp.adapter.ts +0 -48
- package/src/image-compressor-sharp.adapter.ts +0 -50
- package/src/image-exif-clear-sharp.adapter.ts +0 -45
- package/src/image-formatter-sharp.adapter.ts +0 -55
- package/src/image-grayscale-sharp.adapter.ts +0 -45
- package/src/image-info-sharp.adapter.ts +0 -49
- package/src/image-processor-sharp.adapter.ts +0 -73
- package/src/image-resizer-sharp.adapter.ts +0 -56
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
5
|
-
import type { ImageBlurPort, ImageBlurStrategy } from "./image-blur.port";
|
|
6
|
-
|
|
7
|
-
export const ImageBlurSharpAdapterError = {
|
|
8
|
-
MissingDependency: "image.blur.sharp.adapter.error.missing.dependency",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type Dependencies = { FileRenamer: FileRenamerPort };
|
|
12
|
-
type Sharp = typeof sharp;
|
|
13
|
-
|
|
14
|
-
export class ImageBlurSharpAdapter implements ImageBlurPort {
|
|
15
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
16
|
-
"sharp",
|
|
17
|
-
ImageBlurSharpAdapterError.MissingDependency,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
private constructor(
|
|
21
|
-
private readonly sharp: Sharp,
|
|
22
|
-
private readonly deps: Dependencies,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
static async build(deps: Dependencies): Promise<ImageBlurSharpAdapter> {
|
|
26
|
-
const library = await ImageBlurSharpAdapter.importer.resolve();
|
|
27
|
-
|
|
28
|
-
return new ImageBlurSharpAdapter(library.default, deps);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async blur(recipe: ImageBlurStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
32
|
-
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
33
|
-
|
|
34
|
-
const filename = final.getFilename();
|
|
35
|
-
const temporary = final.withFilename(filename.withSuffix("-blurred"));
|
|
36
|
-
|
|
37
|
-
const extension = final.getFilename().getExtension();
|
|
38
|
-
const format = (extension === "jpg" ? "jpeg" : extension) as keyof import("sharp").FormatEnum;
|
|
39
|
-
|
|
40
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
41
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
42
|
-
|
|
43
|
-
await pipeline.rotate().blur(recipe.sigma).toFormat(format).toFile(temporary.get());
|
|
44
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
45
|
-
|
|
46
|
-
return final;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
5
|
-
import type { ImageCompressorPort, ImageCompressorStrategy } from "./image-compressor.port";
|
|
6
|
-
|
|
7
|
-
export const ImageCompressorSharpAdapterError = {
|
|
8
|
-
MissingDependency: "image.compressor.sharp.adapter.error.missing.dependency",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type Dependencies = { FileRenamer: FileRenamerPort };
|
|
12
|
-
type Sharp = typeof sharp;
|
|
13
|
-
|
|
14
|
-
export class ImageCompressorSharpAdapter implements ImageCompressorPort {
|
|
15
|
-
private static readonly DEFAULT_QUALITY = 85;
|
|
16
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
17
|
-
"sharp",
|
|
18
|
-
ImageCompressorSharpAdapterError.MissingDependency,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
private constructor(
|
|
22
|
-
private readonly sharp: Sharp,
|
|
23
|
-
private readonly deps: Dependencies,
|
|
24
|
-
) {}
|
|
25
|
-
|
|
26
|
-
static async build(deps: Dependencies): Promise<ImageCompressorSharpAdapter> {
|
|
27
|
-
const library = await ImageCompressorSharpAdapter.importer.resolve();
|
|
28
|
-
|
|
29
|
-
return new ImageCompressorSharpAdapter(library.default, deps);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async compress(recipe: ImageCompressorStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
33
|
-
const quality = recipe.quality ?? ImageCompressorSharpAdapter.DEFAULT_QUALITY;
|
|
34
|
-
|
|
35
|
-
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
36
|
-
const filename = final.getFilename();
|
|
37
|
-
const temporary = final.withFilename(filename.withSuffix("-compressed"));
|
|
38
|
-
|
|
39
|
-
const extension = final.getFilename().getExtension();
|
|
40
|
-
const format = (extension === "jpg" ? "jpeg" : extension) as keyof import("sharp").FormatEnum;
|
|
41
|
-
|
|
42
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
43
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
44
|
-
|
|
45
|
-
await pipeline.rotate().toFormat(format, { quality }).toFile(temporary.get());
|
|
46
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
47
|
-
|
|
48
|
-
return final;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
5
|
-
import type { ImageExifClearPort, ImageExifClearStrategy } from "./image-exif-clear.port";
|
|
6
|
-
|
|
7
|
-
export const ImageExifClearSharpAdapterError = {
|
|
8
|
-
MissingDependency: "image.exif.clear.sharp.adapter.error.missing.dependency",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type Dependencies = { FileRenamer: FileRenamerPort };
|
|
12
|
-
type Sharp = typeof sharp;
|
|
13
|
-
|
|
14
|
-
export class ImageExifClearSharpAdapter implements ImageExifClearPort {
|
|
15
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
16
|
-
"sharp",
|
|
17
|
-
ImageExifClearSharpAdapterError.MissingDependency,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
private constructor(
|
|
21
|
-
private readonly sharp: Sharp,
|
|
22
|
-
private readonly deps: Dependencies,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
static async build(deps: Dependencies): Promise<ImageExifClearSharpAdapter> {
|
|
26
|
-
const library = await ImageExifClearSharpAdapter.importer.resolve();
|
|
27
|
-
|
|
28
|
-
return new ImageExifClearSharpAdapter(library.default, deps);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async clear(recipe: ImageExifClearStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
32
|
-
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
33
|
-
|
|
34
|
-
const filename = final.getFilename();
|
|
35
|
-
const temporary = final.withFilename(filename.withSuffix("-exif-cleared"));
|
|
36
|
-
|
|
37
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
38
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
39
|
-
|
|
40
|
-
await pipeline.rotate().toFile(temporary.get());
|
|
41
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
42
|
-
|
|
43
|
-
return final;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileCleanerPort } from "./file-cleaner.port";
|
|
5
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
6
|
-
import type { ImageFormatterPort, ImageFormatterStrategy } from "./image-formatter.port";
|
|
7
|
-
|
|
8
|
-
export const ImageFormatterSharpAdapterError = {
|
|
9
|
-
MissingDependency: "image.formatter.sharp.adapter.error.missing.dependency",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type Dependencies = { FileCleaner: FileCleanerPort; FileRenamer: FileRenamerPort };
|
|
13
|
-
type Sharp = typeof sharp;
|
|
14
|
-
|
|
15
|
-
export class ImageFormatterSharpAdapter implements ImageFormatterPort {
|
|
16
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
17
|
-
"sharp",
|
|
18
|
-
ImageFormatterSharpAdapterError.MissingDependency,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
private constructor(
|
|
22
|
-
private readonly sharp: Sharp,
|
|
23
|
-
private readonly deps: Dependencies,
|
|
24
|
-
) {}
|
|
25
|
-
|
|
26
|
-
static async build(deps: Dependencies): Promise<ImageFormatterSharpAdapter> {
|
|
27
|
-
const library = await ImageFormatterSharpAdapter.importer.resolve();
|
|
28
|
-
|
|
29
|
-
return new ImageFormatterSharpAdapter(library.default, deps);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async format(recipe: ImageFormatterStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
33
|
-
const final =
|
|
34
|
-
recipe.strategy === "output_path"
|
|
35
|
-
? recipe.output
|
|
36
|
-
: recipe.input.withFilename(recipe.input.getFilename().withExtension(recipe.to));
|
|
37
|
-
|
|
38
|
-
const temporary = final.withFilename(final.getFilename().withSuffix("-formatted"));
|
|
39
|
-
|
|
40
|
-
const extension = final.getFilename().getExtension();
|
|
41
|
-
const encoder = (extension === "jpg" ? "jpeg" : extension) as keyof import("sharp").FormatEnum;
|
|
42
|
-
|
|
43
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
44
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
45
|
-
|
|
46
|
-
await pipeline.toFormat(encoder).toFile(temporary.get());
|
|
47
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
48
|
-
|
|
49
|
-
if (recipe.strategy === "in_place" && final.get() !== recipe.input.get()) {
|
|
50
|
-
await this.deps.FileCleaner.delete(recipe.input.get());
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return final;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
5
|
-
import type { ImageGrayscalePort, ImageGrayscaleStrategy } from "./image-grayscale.port";
|
|
6
|
-
|
|
7
|
-
export const ImageGrayscaleSharpAdapterError = {
|
|
8
|
-
MissingDependency: "image.grayscale.sharp.adapter.error.missing.dependency",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type Dependencies = { FileRenamer: FileRenamerPort };
|
|
12
|
-
type Sharp = typeof sharp;
|
|
13
|
-
|
|
14
|
-
export class ImageGrayscaleSharpAdapter implements ImageGrayscalePort {
|
|
15
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
16
|
-
"sharp",
|
|
17
|
-
ImageGrayscaleSharpAdapterError.MissingDependency,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
private constructor(
|
|
21
|
-
private readonly sharp: Sharp,
|
|
22
|
-
private readonly deps: Dependencies,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
static async build(deps: Dependencies): Promise<ImageGrayscaleSharpAdapter> {
|
|
26
|
-
const library = await ImageGrayscaleSharpAdapter.importer.resolve();
|
|
27
|
-
|
|
28
|
-
return new ImageGrayscaleSharpAdapter(library.default, deps);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async grayscale(recipe: ImageGrayscaleStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
32
|
-
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
33
|
-
|
|
34
|
-
const filename = final.getFilename();
|
|
35
|
-
const temporary = final.withFilename(filename.withSuffix("-grayscale"));
|
|
36
|
-
|
|
37
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
38
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
39
|
-
|
|
40
|
-
await pipeline.rotate().grayscale().toFile(temporary.get());
|
|
41
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
42
|
-
|
|
43
|
-
return final;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import * as v from "valibot";
|
|
4
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
5
|
-
import type { FileInspectionPort } from "./file-inspection.port";
|
|
6
|
-
import type { ImageInfoPort, ImageInfoType } from "./image-info.port";
|
|
7
|
-
|
|
8
|
-
export const ImageInfoSharpAdapterError = {
|
|
9
|
-
MissingDependency: "image.info.sharp.adapter.error.missing.dependency",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type Dependencies = { FileInspection: FileInspectionPort; MimeRegistry: tools.MimeRegistry };
|
|
13
|
-
type Sharp = typeof sharp;
|
|
14
|
-
|
|
15
|
-
export class ImageInfoSharpAdapter implements ImageInfoPort {
|
|
16
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
17
|
-
"sharp",
|
|
18
|
-
ImageInfoSharpAdapterError.MissingDependency,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
private constructor(
|
|
22
|
-
private readonly sharp: Sharp,
|
|
23
|
-
private readonly deps: Dependencies,
|
|
24
|
-
) {}
|
|
25
|
-
|
|
26
|
-
static async build(deps: Dependencies): Promise<ImageInfoSharpAdapter> {
|
|
27
|
-
const library = await ImageInfoSharpAdapter.importer.resolve();
|
|
28
|
-
|
|
29
|
-
return new ImageInfoSharpAdapter(library.default, deps);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async inspect(input: tools.FilePathRelative | tools.FilePathAbsolute): Promise<ImageInfoType> {
|
|
33
|
-
const size = await this.deps.FileInspection.size(input);
|
|
34
|
-
|
|
35
|
-
const pipeline = this.sharp(input.get());
|
|
36
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
37
|
-
|
|
38
|
-
const metadata = await pipeline.metadata();
|
|
39
|
-
|
|
40
|
-
const width = v.parse(tools.ImageWidth, metadata.width);
|
|
41
|
-
const height = v.parse(tools.ImageHeight, metadata.height);
|
|
42
|
-
const extension = v.parse(tools.Extension, metadata.format);
|
|
43
|
-
const mime = this.deps.MimeRegistry.fromExtension(extension);
|
|
44
|
-
|
|
45
|
-
if (!mime) throw new Error(tools.MimeRegistryError.MimeNotFound);
|
|
46
|
-
|
|
47
|
-
return { width, height, mime, size };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileCleanerPort } from "./file-cleaner.port";
|
|
5
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
6
|
-
import type { ImageProcessorPort, ImageProcessorStrategy } from "./image-processor.port";
|
|
7
|
-
|
|
8
|
-
export const ImageProcessorSharpAdapterError = {
|
|
9
|
-
MissingDependency: "image.processor.sharp.adapter.error.missing.dependency",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type Dependencies = { FileCleaner: FileCleanerPort; FileRenamer: FileRenamerPort };
|
|
13
|
-
type Sharp = typeof sharp;
|
|
14
|
-
|
|
15
|
-
export class ImageProcessorSharpAdapter implements ImageProcessorPort {
|
|
16
|
-
private static readonly DEFAULT_QUALITY = 85;
|
|
17
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
18
|
-
"sharp",
|
|
19
|
-
ImageProcessorSharpAdapterError.MissingDependency,
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
private constructor(
|
|
23
|
-
private readonly sharp: Sharp,
|
|
24
|
-
private readonly deps: Dependencies,
|
|
25
|
-
) {}
|
|
26
|
-
|
|
27
|
-
static async build(deps: Dependencies): Promise<ImageProcessorSharpAdapter> {
|
|
28
|
-
const library = await ImageProcessorSharpAdapter.importer.resolve();
|
|
29
|
-
|
|
30
|
-
return new ImageProcessorSharpAdapter(library.default, deps);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async process(recipe: ImageProcessorStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
34
|
-
const final =
|
|
35
|
-
recipe.strategy === "output_path"
|
|
36
|
-
? recipe.output
|
|
37
|
-
: recipe.input.withFilename(recipe.input.getFilename().withExtension(recipe.to));
|
|
38
|
-
|
|
39
|
-
const temporary = final.withFilename(final.getFilename().withSuffix("-processed"));
|
|
40
|
-
|
|
41
|
-
const extension = final.getFilename().getExtension();
|
|
42
|
-
const encoder = (extension === "jpg" ? "jpeg" : extension) as keyof import("sharp").FormatEnum;
|
|
43
|
-
|
|
44
|
-
const quality = recipe.quality ?? ImageProcessorSharpAdapter.DEFAULT_QUALITY;
|
|
45
|
-
|
|
46
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
47
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
48
|
-
|
|
49
|
-
let processor = pipeline.rotate();
|
|
50
|
-
|
|
51
|
-
if (recipe.background) {
|
|
52
|
-
processor = processor.flatten({ background: recipe.background });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
processor = processor.resize({
|
|
56
|
-
width: recipe.maxSide,
|
|
57
|
-
height: recipe.maxSide,
|
|
58
|
-
fit: "inside",
|
|
59
|
-
withoutEnlargement: true,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
processor = processor.toFormat(encoder, { quality });
|
|
63
|
-
|
|
64
|
-
await processor.toFile(temporary.get());
|
|
65
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
66
|
-
|
|
67
|
-
if (recipe.strategy === "in_place" && final.get() !== recipe.input.get()) {
|
|
68
|
-
await this.deps.FileCleaner.delete(recipe.input.get());
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return final;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
|
-
import type sharp from "sharp";
|
|
3
|
-
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
-
import type { FileRenamerPort } from "./file-renamer.port";
|
|
5
|
-
import type { ImageResizerPort, ImageResizerStrategy } from "./image-resizer.port";
|
|
6
|
-
|
|
7
|
-
export const ImageResizerSharpAdapterError = {
|
|
8
|
-
MissingDependency: "image.resizer.sharp.adapter.error.missing.dependency",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type Dependencies = { FileRenamer: FileRenamerPort };
|
|
12
|
-
type Sharp = typeof sharp;
|
|
13
|
-
|
|
14
|
-
export class ImageResizerSharpAdapter implements ImageResizerPort {
|
|
15
|
-
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
16
|
-
"sharp",
|
|
17
|
-
ImageResizerSharpAdapterError.MissingDependency,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
private constructor(
|
|
21
|
-
private readonly sharp: Sharp,
|
|
22
|
-
private readonly deps: Dependencies,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
static async build(deps: Dependencies): Promise<ImageResizerSharpAdapter> {
|
|
26
|
-
const library = await ImageResizerSharpAdapter.importer.resolve();
|
|
27
|
-
|
|
28
|
-
return new ImageResizerSharpAdapter(library.default, deps);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async resize(recipe: ImageResizerStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
32
|
-
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
33
|
-
const filename = final.getFilename();
|
|
34
|
-
const temporary = final.withFilename(filename.withSuffix("-resized"));
|
|
35
|
-
|
|
36
|
-
const extension = final.getFilename().getExtension();
|
|
37
|
-
const format = (extension === "jpg" ? "jpeg" : extension) as keyof import("sharp").FormatEnum;
|
|
38
|
-
|
|
39
|
-
const pipeline = this.sharp(recipe.input.get());
|
|
40
|
-
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
41
|
-
|
|
42
|
-
await pipeline
|
|
43
|
-
.rotate()
|
|
44
|
-
.resize({
|
|
45
|
-
width: recipe.maxSide,
|
|
46
|
-
height: recipe.maxSide,
|
|
47
|
-
fit: "inside",
|
|
48
|
-
withoutEnlargement: true,
|
|
49
|
-
})
|
|
50
|
-
.toFormat(format)
|
|
51
|
-
.toFile(temporary.get());
|
|
52
|
-
await this.deps.FileRenamer.rename(temporary, final);
|
|
53
|
-
|
|
54
|
-
return final;
|
|
55
|
-
}
|
|
56
|
-
}
|