vona-module-image-native 5.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016-present Cabloy/Vona/Zova
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,87 @@
1
+ /** service: begin */
2
+ export * from '../service/imageNative.ts';
3
+ import 'vona-module-a-bean';
4
+ declare module 'vona-module-a-bean' {
5
+ interface IServiceRecord {
6
+ 'image-native:imageNative': never;
7
+ }
8
+ }
9
+ declare module 'vona-module-image-native' {
10
+ interface ServiceImageNative {
11
+ }
12
+ interface ServiceImageNative {
13
+ get $beanFullName(): 'image-native.service.imageNative';
14
+ get $onionName(): 'image-native:imageNative';
15
+ }
16
+ }
17
+ /** service: end */
18
+ /** service: begin */
19
+ import type { ServiceImageNative } from '../service/imageNative.ts';
20
+ export interface IModuleService {
21
+ 'imageNative': ServiceImageNative;
22
+ }
23
+ /** service: end */
24
+ /** service: begin */
25
+ import 'vona';
26
+ declare module 'vona' {
27
+ interface IBeanRecordGeneral {
28
+ 'image-native.service.imageNative': ServiceImageNative;
29
+ }
30
+ }
31
+ /** service: end */
32
+ /** imageProvider: begin */
33
+ export * from '../bean/imageProvider.native.ts';
34
+ import type { IImageProviderOptionsNative } from '../bean/imageProvider.native.ts';
35
+ import 'vona-module-a-image';
36
+ declare module 'vona-module-a-image' {
37
+ interface IImageProviderRecord {
38
+ 'image-native:native': IImageProviderOptionsNative;
39
+ }
40
+ }
41
+ declare module 'vona-module-image-native' {
42
+ interface ImageProviderNative {
43
+ }
44
+ interface ImageProviderNative {
45
+ get $beanFullName(): 'image-native.imageProvider.native';
46
+ get $onionName(): 'image-native:native';
47
+ get $onionOptions(): IImageProviderOptionsNative;
48
+ }
49
+ }
50
+ /** imageProvider: end */
51
+ /** imageProvider: begin */
52
+ import type { ImageProviderNative } from '../bean/imageProvider.native.ts';
53
+ export interface IModuleImageProvider {
54
+ 'native': ImageProviderNative;
55
+ }
56
+ /** imageProvider: end */
57
+ /** config: begin */
58
+ export * from '../config/config.ts';
59
+ import type { config } from '../config/config.ts';
60
+ /** config: end */
61
+ /** monkey: begin */
62
+ export * from '../monkey.ts';
63
+ /** monkey: end */
64
+ /** scope: begin */
65
+ import { BeanScopeBase, type BeanScopeUtil, type TypeModuleConfig } from 'vona';
66
+ export declare class ScopeModuleImageNative extends BeanScopeBase {
67
+ }
68
+ export interface ScopeModuleImageNative {
69
+ util: BeanScopeUtil;
70
+ config: TypeModuleConfig<typeof config>;
71
+ service: IModuleService;
72
+ imageProvider: IModuleImageProvider;
73
+ }
74
+ import 'vona';
75
+ declare module 'vona' {
76
+ interface IBeanScopeRecord {
77
+ 'image-native': ScopeModuleImageNative;
78
+ }
79
+ interface IBeanScopeContainer {
80
+ imageNative: ScopeModuleImageNative;
81
+ }
82
+ interface IBeanScopeConfig {
83
+ 'image-native': ReturnType<typeof config>;
84
+ }
85
+ }
86
+ /** scope: end */
87
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/.metadata/index.ts"],"names":[],"mappings":"AACA,qBAAqB;AACrB,cAAc,2BAA2B,CAAC;AAE1C,OAAO,oBAAoB,CAAC;AAC5B,OAAO,QAAQ,oBAAoB,CAAC;IAEhC,UAAiB,cAAc;QAC7B,0BAA0B,EAAE,KAAK,CAAC;KACnC;CAGJ;AACD,OAAO,QAAQ,0BAA0B,CAAC;IAElC,UAAiB,kBAAkB;KAGlC;IAEC,UAAiB,kBAAkB;QACjC,IAAI,aAAa,IAAI,kCAAkC,CAAC;QACxD,IAAI,UAAU,IAAI,0BAA0B,CAAC;KAE9C;CACV;AACD,mBAAmB;AACnB,qBAAqB;AACrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,kBAAkB,CAAC;CACnC;AACD,mBAAmB;AACnB,qBAAqB;AAErB,OAAO,MAAM,CAAC;AACd,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAiB,kBAAkB;QACjC,kCAAkC,EAAE,kBAAkB,CAAC;KACxD;CACF;AACD,mBAAmB;AACnB,2BAA2B;AAC3B,cAAc,iCAAiC,CAAC;AAChD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,qBAAqB,CAAC;AAC7B,OAAO,QAAQ,qBAAqB,CAAC;IAEjC,UAAiB,oBAAoB;QACnC,qBAAqB,EAAE,2BAA2B,CAAC;KACpD;CAGJ;AACD,OAAO,QAAQ,0BAA0B,CAAC;IAElC,UAAiB,mBAAmB;KAGnC;IAEC,UAAiB,mBAAmB;QAClC,IAAI,aAAa,IAAI,mCAAmC,CAAC;QACzD,IAAI,UAAU,IAAI,qBAAqB,CAAC;QACxC,IAAI,aAAa,IAAI,2BAA2B,CAAC;KAClD;CACV;AACD,yBAAyB;AACzB,2BAA2B;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AACD,yBAAyB;AACzB,oBAAoB;AACpB,cAAc,qBAAqB,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,kBAAkB;AAClB,oBAAoB;AACpB,cAAc,cAAc,CAAC;AAC7B,kBAAkB;AAClB,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAGhF,qBACa,sBAAuB,SAAQ,aAAa;CAAG;AAE5D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,gBAAgB,CAAC,OAAO,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,cAAc,CAAC;IACxB,aAAa,EAAE,oBAAoB,CAAC;CACnC;AAED,OAAO,MAAM,CAAC;AACd,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAiB,gBAAgB;QAC/B,cAAc,EAAE,sBAAsB,CAAC;KACxC;IAED,UAAiB,mBAAmB;QAClC,WAAW,EAAE,sBAAsB,CAAC;KACrC;IAED,UAAiB,gBAAgB;QAC/B,cAAc,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;KAC3C;CAKF;AACD,iBAAiB"}
@@ -0,0 +1,3 @@
1
+ export declare const __ThisModule__ = "image-native";
2
+ export { ScopeModuleImageNative as ScopeModule } from './index.ts';
3
+ //# sourceMappingURL=this.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"this.d.ts","sourceRoot":"","sources":["../../src/.metadata/this.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,IAAI,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { IDecoratorImageProviderOptions, IImageDeliveryOptions, IImageDownloadResult, IImageProviderClientOptions, IImageProviderClientRecord, IImageProviderExecute, IImageProviderResource, IImageUploadInput, IImageVariantRequest } from 'vona-module-a-image';
2
+ import type { EntityImage } from 'vona-module-a-image';
3
+ import { BeanBase } from 'vona';
4
+ export interface IImageProviderNativeClientRecord extends IImageProviderClientRecord {
5
+ }
6
+ export interface IImageProviderNativeClientOptions extends IImageProviderClientOptions {
7
+ subdir?: string;
8
+ signingKey?: string;
9
+ tokenName?: string;
10
+ }
11
+ export interface IImageProviderOptionsNative extends IDecoratorImageProviderOptions<IImageProviderNativeClientRecord, IImageProviderNativeClientOptions> {
12
+ }
13
+ export declare class ImageProviderNative extends BeanBase implements IImageProviderExecute {
14
+ upload(input: IImageUploadInput, clientOptions: IImageProviderNativeClientOptions, _options: IImageProviderOptionsNative): Promise<IImageProviderResource>;
15
+ get(image: EntityImage, clientOptions: IImageProviderNativeClientOptions, _options: IImageProviderOptionsNative): Promise<{
16
+ resourceId: string;
17
+ filename: string | undefined;
18
+ contentType: string | undefined;
19
+ size: number | undefined;
20
+ width: number | undefined;
21
+ height: number | undefined;
22
+ requireSignedURLs: boolean | undefined;
23
+ variants: Partial<Record<keyof import("vona-module-a-image").IImageVariantNameRecord, import("vona-module-a-image").IImageTransformOptions>> | undefined;
24
+ meta: Record<string, any> | undefined;
25
+ storagePath: string | undefined;
26
+ deliveryBaseUrl: string | undefined;
27
+ }>;
28
+ delete(image: EntityImage, _clientOptions: IImageProviderClientOptions, _options: IImageProviderOptionsNative): Promise<void>;
29
+ getVariantUrl(image: EntityImage, request: IImageVariantRequest, clientOptions: IImageProviderNativeClientOptions, _options: IImageProviderOptionsNative, deliveryOptions?: IImageDeliveryOptions): Promise<string>;
30
+ download(image: EntityImage, request: IImageVariantRequest, clientOptions: IImageProviderNativeClientOptions, options: IImageProviderOptionsNative, deliveryOptions?: IImageDeliveryOptions): Promise<IImageDownloadResult>;
31
+ }
32
+ //# sourceMappingURL=imageProvider.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageProvider.native.d.ts","sourceRoot":"","sources":["../../src/bean/imageProvider.native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAGhC,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;CAAG;AAEvF,MAAM,WAAW,iCAAkC,SAAQ,2BAA2B;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,2BAA4B,SAAQ,8BAA8B,CACjF,gCAAgC,EAChC,iCAAiC,CAClC;CAAG;AAEJ,qBAMa,mBAAoB,SAAQ,QAAS,YAAW,qBAAqB;IAC1E,MAAM,CACV,KAAK,EAAE,iBAAiB,EACxB,aAAa,EAAE,iCAAiC,EAChD,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC,sBAAsB,CAAC;IAU5B,GAAG,CACP,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,iCAAiC,EAChD,QAAQ,EAAE,2BAA2B;;;;;;;;;;;;;IAiBjC,MAAM,CACV,KAAK,EAAE,WAAW,EAClB,cAAc,EAAE,2BAA2B,EAC3C,QAAQ,EAAE,2BAA2B;IAKjC,aAAa,CACjB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,iCAAiC,EAChD,QAAQ,EAAE,2BAA2B,EACrC,eAAe,CAAC,EAAE,qBAAqB;IAcnC,QAAQ,CACZ,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,iCAAiC,EAChD,OAAO,EAAE,2BAA2B,EACpC,eAAe,CAAC,EAAE,qBAAqB,GACtC,OAAO,CAAC,oBAAoB,CAAC;CA0BjC"}
@@ -0,0 +1,9 @@
1
+ import type { VonaApplication } from 'vona';
2
+ export declare function config(_app: VonaApplication): {
3
+ imageNative: {
4
+ variants: {
5
+ original: {};
6
+ };
7
+ };
8
+ };
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAE5C,wBAAgB,MAAM,CAAC,IAAI,EAAE,eAAe;;;;;;EAQ3C"}
@@ -0,0 +1,2 @@
1
+ export * from './.metadata/index.ts';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,324 @@
1
+ import { BeanInfo, BeanBase, uuidv4, BeanSimple, cast, getPlatformArch, resolveAddon, BeanScopeBase } from 'vona';
2
+ import { __decorate } from 'tslib';
3
+ import fse from 'fs-extra';
4
+ import { createHash } from 'node:crypto';
5
+ import path from 'node:path';
6
+ import { Service, Scope } from 'vona-module-a-bean';
7
+ import { resolveImageVariantRequestToTransform, ImageProvider } from 'vona-module-a-image';
8
+
9
+ let ServiceImageNative = class ServiceImageNative extends BeanBase {
10
+ constructor(...args) {
11
+ super(...args);
12
+ this._sharpInstance = void 0;
13
+ }
14
+ async getSharp() {
15
+ if (!this._sharpInstance) {
16
+ this._sharpInstance = (await import('sharp')).default;
17
+ }
18
+ return this._sharpInstance;
19
+ }
20
+ async upload(input, options) {
21
+ const publicPath = await this.app.util.getPublicPathPhysical(path.join('image-native', options.subdir ?? 'default'), true);
22
+ const resourceId = uuidv4();
23
+ const ext = this._getOriginalExt(input.filename, input.file);
24
+ const targetName = `${resourceId}${ext}`;
25
+ const targetPath = path.join(publicPath, targetName);
26
+ await fse.copy(input.file, targetPath);
27
+ const sharp = await this.getSharp();
28
+ const metadata = await sharp(targetPath).metadata();
29
+ const stat = await fse.stat(targetPath);
30
+ const variants = options.variants ?? this.scope.config.imageNative.variants;
31
+ await this._generateNamedVariants({
32
+ resourceId,
33
+ filename: input.filename,
34
+ storagePath: targetPath,
35
+ variants
36
+ }, options);
37
+ return {
38
+ resourceId,
39
+ size: Number(stat.size),
40
+ width: metadata.width,
41
+ height: metadata.height,
42
+ storagePath: targetPath,
43
+ deliveryBaseUrl: options.deliveryBaseUrl,
44
+ requireSignedURLs: input.requireSignedURLs ?? options.requireSignedURLs,
45
+ variants
46
+ };
47
+ }
48
+ async remove(image) {
49
+ if (!image.storagePath) return;
50
+ const dir = path.dirname(image.storagePath);
51
+ if (!(await fse.pathExists(dir))) return;
52
+ const entries = await fse.readdir(dir);
53
+ await Promise.all(entries.filter(name => name === path.basename(image.storagePath) || name.startsWith(`${image.resourceId}__`)).map(name => fse.remove(path.join(dir, name))));
54
+ }
55
+ async getVariantUrl(image, request, options, _deliveryOptions) {
56
+ const resolved = resolveImageVariantRequestToTransform(request, 'original', image.variants);
57
+ if (resolved.variantName === 'original' && this._isOriginalTransform(resolved.transformOptions)) {
58
+ return await this._getOriginalUrl(image, options);
59
+ }
60
+ const targetPath = await this._ensureVariantFile(image, resolved);
61
+ return await this._buildUrl(targetPath, options.deliveryBaseUrl);
62
+ }
63
+ async _generateNamedVariants(image, options) {
64
+ const variantNames = Object.keys(image.variants ?? {});
65
+ for (const variantName of variantNames) {
66
+ if (variantName === 'original') continue;
67
+ await this._ensureVariantFile(image, resolveImageVariantRequestToTransform({
68
+ variantName
69
+ }, 'original', image.variants));
70
+ }
71
+ if (!image.variants?.original) return;
72
+ await this.getVariantUrl(image, {
73
+ variantName: 'original'
74
+ }, options);
75
+ }
76
+ async _ensureVariantFile(image, resolved) {
77
+ if (!image.storagePath) {
78
+ throw new Error(`Image storage path missing: ${image.resourceId}`);
79
+ }
80
+ const targetPath = await this._getVariantAbsolutePath(image, resolved);
81
+ if (!(await fse.pathExists(targetPath))) {
82
+ await this._writeTransformedFile(image.storagePath, targetPath, resolved.transformOptions);
83
+ }
84
+ return targetPath;
85
+ }
86
+ async _writeTransformedFile(sourcePath, targetPath, transformOptions) {
87
+ await fse.ensureDir(path.dirname(targetPath));
88
+ if (this._isOriginalTransform(transformOptions)) {
89
+ await fse.copy(sourcePath, targetPath, {
90
+ overwrite: true
91
+ });
92
+ return;
93
+ }
94
+ const sharp = await this.getSharp();
95
+ let pipeline = sharp(sourcePath, {
96
+ failOn: 'none'
97
+ });
98
+ const width = transformOptions.width && transformOptions.dpr ? Math.round(transformOptions.width * transformOptions.dpr) : transformOptions.width;
99
+ const height = transformOptions.height && transformOptions.dpr ? Math.round(transformOptions.height * transformOptions.dpr) : transformOptions.height;
100
+ if (width || height || transformOptions.fit || transformOptions.gravity || transformOptions.background) {
101
+ pipeline = pipeline.resize({
102
+ width,
103
+ height,
104
+ fit: this._mapFit(transformOptions.fit),
105
+ position: this._mapGravity(transformOptions.gravity),
106
+ background: transformOptions.background
107
+ });
108
+ }
109
+ if (transformOptions.rotate !== undefined) {
110
+ pipeline = pipeline.rotate(transformOptions.rotate);
111
+ }
112
+ if (transformOptions.sharpen !== undefined) {
113
+ pipeline = pipeline.sharpen({
114
+ sigma: transformOptions.sharpen
115
+ });
116
+ }
117
+ const format = this._normalizeFormat(transformOptions.format);
118
+ if (format === 'jpeg') {
119
+ pipeline = pipeline.jpeg({
120
+ quality: transformOptions.quality
121
+ });
122
+ } else if (format === 'png') {
123
+ pipeline = pipeline.png({
124
+ quality: transformOptions.quality
125
+ });
126
+ } else if (format === 'webp') {
127
+ pipeline = pipeline.webp({
128
+ quality: transformOptions.quality
129
+ });
130
+ } else if (format === 'avif') {
131
+ pipeline = pipeline.avif({
132
+ quality: transformOptions.quality
133
+ });
134
+ }
135
+ await pipeline.toFile(targetPath);
136
+ }
137
+ async _getOriginalUrl(image, options) {
138
+ if (!image.storagePath) {
139
+ throw new Error(`Image storage path missing: ${image.resourceId}`);
140
+ }
141
+ return await this._buildUrl(image.storagePath, options.deliveryBaseUrl);
142
+ }
143
+ async _buildUrl(targetPath, deliveryBaseUrl) {
144
+ const variantPath = await this._getVariantStaticPath(targetPath);
145
+ if (deliveryBaseUrl) {
146
+ return `${deliveryBaseUrl.replace(/\/$/, '')}/${variantPath}`;
147
+ }
148
+ return this.app.util.combineStaticPath(`/${variantPath}`);
149
+ }
150
+ async _getVariantStaticPath(targetPath) {
151
+ const publicRoot = await this.app.util.getPublicPathPhysical(undefined, true);
152
+ const relativePath = path.relative(publicRoot, targetPath).split(path.sep).join(path.posix.sep);
153
+ return path.posix.join('public', this.ctx.instance.id.toString(), relativePath);
154
+ }
155
+ async _getVariantAbsolutePath(image, resolved) {
156
+ if (!image.storagePath) throw new Error(`Image storage path missing: ${image.resourceId}`);
157
+ const dir = path.dirname(image.storagePath);
158
+ const ext = this._getVariantExt(image.filename, image.storagePath, resolved.transformOptions);
159
+ if (resolved.variantName !== 'custom') {
160
+ const variantName = this._sanitizeVariantName(resolved.variantName);
161
+ return path.join(dir, `${image.resourceId}__${variantName}${ext}`);
162
+ }
163
+ const cacheKey = this._buildTransformCacheKey(resolved.transformOptions);
164
+ return path.join(dir, `${image.resourceId}__t_${cacheKey}${ext}`);
165
+ }
166
+ _getVariantExt(filename, storagePath, transformOptions) {
167
+ const format = this._normalizeFormat(transformOptions.format);
168
+ if (format) {
169
+ return format === 'jpeg' ? '.jpg' : `.${format}`;
170
+ }
171
+ return path.extname(filename ?? '') || path.extname(storagePath ?? '') || '.bin';
172
+ }
173
+ _getOriginalExt(filename, filePath) {
174
+ return path.extname(filename ?? '') || path.extname(filePath) || '.bin';
175
+ }
176
+ _normalizeFormat(format) {
177
+ if (!format || format === 'auto') return undefined;
178
+ return format === 'jpeg' ? 'jpeg' : format;
179
+ }
180
+ _buildTransformCacheKey(transformOptions) {
181
+ const stable = this._stableStringify(transformOptions);
182
+ return createHash('sha1').update(stable).digest('hex').slice(0, 12);
183
+ }
184
+ _stableStringify(value) {
185
+ if (Array.isArray(value)) {
186
+ return `[${value.map(item => this._stableStringify(item)).join(',')}]`;
187
+ }
188
+ if (value && typeof value === 'object') {
189
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
190
+ return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${this._stableStringify(item)}`).join(',')}}`;
191
+ }
192
+ return JSON.stringify(value);
193
+ }
194
+ _sanitizeVariantName(variantName) {
195
+ return variantName.replace(/[^\w.-]/g, '-');
196
+ }
197
+ _isOriginalTransform(transformOptions) {
198
+ return Object.keys(transformOptions).length === 0;
199
+ }
200
+ _mapFit(fit) {
201
+ if (fit === 'scale-down') return 'inside';
202
+ if (fit === 'contain' || fit === 'pad') return 'contain';
203
+ if (fit === 'cover' || fit === 'crop') return 'cover';
204
+ return undefined;
205
+ }
206
+ _mapGravity(gravity) {
207
+ if (gravity === 'top') return 'north';
208
+ if (gravity === 'bottom') return 'south';
209
+ if (gravity === 'left') return 'west';
210
+ if (gravity === 'right') return 'east';
211
+ return 'centre';
212
+ }
213
+ };
214
+ ServiceImageNative = __decorate([Service(), BeanInfo({
215
+ module: "image-native"
216
+ })], ServiceImageNative);
217
+
218
+ let ImageProviderNative = class ImageProviderNative extends BeanBase {
219
+ async upload(input, clientOptions, _options) {
220
+ const resource = await this.scope.service.imageNative.upload(input, clientOptions);
221
+ return {
222
+ ...resource,
223
+ filename: input.filename,
224
+ contentType: input.contentType,
225
+ meta: input.meta
226
+ };
227
+ }
228
+ async get(image, clientOptions, _options) {
229
+ return {
230
+ resourceId: image.resourceId,
231
+ filename: image.filename,
232
+ contentType: image.contentType,
233
+ size: image.size,
234
+ width: image.width,
235
+ height: image.height,
236
+ requireSignedURLs: image.requireSignedURLs,
237
+ variants: image.variants,
238
+ meta: image.meta,
239
+ storagePath: image.storagePath,
240
+ deliveryBaseUrl: image.deliveryBaseUrl ?? clientOptions.deliveryBaseUrl
241
+ };
242
+ }
243
+ async delete(image, _clientOptions, _options) {
244
+ await this.scope.service.imageNative.remove(image);
245
+ }
246
+ async getVariantUrl(image, request, clientOptions, _options, deliveryOptions) {
247
+ return await this.scope.service.imageNative.getVariantUrl(image, request, {
248
+ ...clientOptions,
249
+ subdir: clientOptions.subdir ?? 'default',
250
+ deliveryBaseUrl: image.deliveryBaseUrl ?? clientOptions.deliveryBaseUrl
251
+ }, deliveryOptions);
252
+ }
253
+ async download(image, request, clientOptions, options, deliveryOptions) {
254
+ if ((deliveryOptions?.responseMode ?? 'auto') !== 'url' && !deliveryOptions?.signed && request.variantName === 'original' && !request.transformOptions) {
255
+ const buffer = image.storagePath ? await fse.readFile(image.storagePath) : undefined;
256
+ if (buffer) {
257
+ return {
258
+ kind: 'buffer',
259
+ buffer,
260
+ filename: image.filename,
261
+ contentType: image.contentType,
262
+ signed: false
263
+ };
264
+ }
265
+ }
266
+ return {
267
+ kind: 'url',
268
+ url: await this.getVariantUrl(image, request, clientOptions, options, deliveryOptions),
269
+ filename: image.filename,
270
+ contentType: image.contentType,
271
+ signed: !!deliveryOptions?.signed
272
+ };
273
+ }
274
+ };
275
+ ImageProviderNative = __decorate([ImageProvider({
276
+ base: {
277
+ subdir: 'default',
278
+ signedDeliveryKind: 'proxy'
279
+ }
280
+ }), BeanInfo({
281
+ module: "image-native"
282
+ })], ImageProviderNative);
283
+
284
+ function config(_app) {
285
+ return {
286
+ imageNative: {
287
+ variants: {
288
+ original: {}
289
+ }
290
+ }
291
+ };
292
+ }
293
+
294
+ const __Version = '8.18.3';
295
+ const __MapTargetNames = {
296
+ 'linux-arm64': `libvips-cpp.so.${__Version}`,
297
+ 'linux-x64': `libvips-cpp.so.${__Version}`,
298
+ 'darwin-arm64': `libvips-cpp.${__Version}.dylib`,
299
+ 'darwin-x64': `libvips-cpp.${__Version}.dylib`,
300
+ 'win32-x64': 'libvips-42.dll'
301
+ };
302
+ class Monkey extends BeanSimple {
303
+ async appStart() {
304
+ cast(this.app).__prepareSharpLibvips = () => {
305
+ const platformArch = getPlatformArch();
306
+ const addonFileSrc = resolveAddon('sharpLibvips');
307
+ const addonDirDest = path.join(import.meta.dirname, `node_modules/@img/sharp-libvips-${platformArch}/lib`);
308
+ const addonFileDest = path.join(addonDirDest, __MapTargetNames[platformArch]);
309
+ if (!fse.existsSync(addonFileDest)) {
310
+ fse.ensureDirSync(addonDirDest);
311
+ fse.copyFileSync(addonFileSrc, addonFileDest);
312
+ }
313
+ };
314
+ }
315
+ }
316
+
317
+ let ScopeModuleImageNative = class ScopeModuleImageNative extends BeanScopeBase {};
318
+ ScopeModuleImageNative = __decorate([Scope(), BeanInfo({
319
+ module: "image-native"
320
+ })], ScopeModuleImageNative);
321
+ /** scope: end */
322
+
323
+ export { ImageProviderNative, Monkey, ScopeModuleImageNative, ServiceImageNative, config };
324
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/service/imageNative.ts","../src/bean/imageProvider.native.ts","../src/config/config.ts","../src/monkey.ts","../src/.metadata/index.ts"],"sourcesContent":[null,null,null,null,null],"names":["ServiceImageNative","BeanBase","constructor","args","_sharpInstance","getSharp","default","upload","input","options","publicPath","app","util","getPublicPathPhysical","path","join","subdir","resourceId","uuidv4","ext","_getOriginalExt","filename","file","targetName","targetPath","fse","copy","sharp","metadata","stat","variants","scope","config","imageNative","_generateNamedVariants","storagePath","size","Number","width","height","deliveryBaseUrl","requireSignedURLs","remove","image","dir","dirname","pathExists","entries","readdir","Promise","all","filter","name","basename","startsWith","map","getVariantUrl","request","_deliveryOptions","resolved","resolveImageVariantRequestToTransform","variantName","_isOriginalTransform","transformOptions","_getOriginalUrl","_ensureVariantFile","_buildUrl","variantNames","Object","keys","original","Error","_getVariantAbsolutePath","_writeTransformedFile","sourcePath","ensureDir","overwrite","pipeline","failOn","dpr","Math","round","fit","gravity","background","resize","_mapFit","position","_mapGravity","rotate","undefined","sharpen","sigma","format","_normalizeFormat","jpeg","quality","png","webp","avif","toFile","variantPath","_getVariantStaticPath","replace","combineStaticPath","publicRoot","relativePath","relative","split","sep","posix","ctx","instance","id","toString","_getVariantExt","_sanitizeVariantName","cacheKey","_buildTransformCacheKey","extname","filePath","stable","_stableStringify","createHash","update","digest","slice","value","Array","isArray","item","sort","a","b","localeCompare","key","JSON","stringify","length","__decorate","Service","__z_BeanInfo","module","ImageProviderNative","clientOptions","_options","resource","service","contentType","meta","get","delete","_clientOptions","deliveryOptions","download","responseMode","signed","buffer","readFile","kind","url","ImageProvider","base","signedDeliveryKind","_app","__Version","__MapTargetNames","Monkey","BeanSimple","appStart","cast","__prepareSharpLibvips","platformArch","getPlatformArch","addonFileSrc","resolveAddon","addonDirDest","import","addonFileDest","existsSync","ensureDirSync","copyFileSync","ScopeModuleImageNative","BeanScopeBase","Scope"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { IMonkeyAppStart } from 'vona';
2
+ import { BeanSimple } from 'vona';
3
+ export declare class Monkey extends BeanSimple implements IMonkeyAppStart {
4
+ appStart(): Promise<void>;
5
+ }
6
+ //# sourceMappingURL=monkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monkey.d.ts","sourceRoot":"","sources":["../src/monkey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAI5C,OAAO,EAAE,UAAU,EAAuC,MAAM,MAAM,CAAC;AAYvE,qBAAa,MAAO,SAAQ,UAAW,YAAW,eAAe;IACzD,QAAQ;CAef"}
@@ -0,0 +1,29 @@
1
+ import type { EntityImage, IImageDeliveryOptions, IImageProviderResource, IImageUploadInput, IImageVariantRequest } from 'vona-module-a-image';
2
+ import { BeanBase } from 'vona';
3
+ import type { IImageProviderNativeClientOptions } from '../bean/imageProvider.native.ts';
4
+ type IImageNativeStoredImage = Pick<EntityImage, 'resourceId' | 'filename' | 'storagePath' | 'variants'>;
5
+ export declare class ServiceImageNative extends BeanBase {
6
+ private _sharpInstance;
7
+ private getSharp;
8
+ upload(input: IImageUploadInput, options: IImageProviderNativeClientOptions): Promise<IImageProviderResource>;
9
+ remove(image: IImageNativeStoredImage): Promise<void>;
10
+ getVariantUrl(image: IImageNativeStoredImage, request: IImageVariantRequest, options: IImageProviderNativeClientOptions, _deliveryOptions?: IImageDeliveryOptions): Promise<string>;
11
+ private _generateNamedVariants;
12
+ private _ensureVariantFile;
13
+ private _writeTransformedFile;
14
+ private _getOriginalUrl;
15
+ private _buildUrl;
16
+ private _getVariantStaticPath;
17
+ private _getVariantAbsolutePath;
18
+ private _getVariantExt;
19
+ private _getOriginalExt;
20
+ private _normalizeFormat;
21
+ private _buildTransformCacheKey;
22
+ private _stableStringify;
23
+ private _sanitizeVariantName;
24
+ private _isOriginalTransform;
25
+ private _mapFit;
26
+ private _mapGravity;
27
+ }
28
+ export {};
29
+ //# sourceMappingURL=imageNative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageNative.d.ts","sourceRoot":"","sources":["../../src/service/imageNative.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EAGrB,sBAAsB,EAEtB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EAAE,QAAQ,EAAU,MAAM,MAAM,CAAC;AAIxC,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AAEzF,KAAK,uBAAuB,GAAG,IAAI,CACjC,WAAW,EACX,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,UAAU,CACvD,CAAC;AAEF,qBACa,kBAAmB,SAAQ,QAAQ;IAC9C,OAAO,CAAC,cAAc,CAAmB;YAE3B,QAAQ;IAOhB,MAAM,CACV,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,sBAAsB,CAAC;IA8B5B,MAAM,CAAC,KAAK,EAAE,uBAAuB;IAerC,aAAa,CACjB,KAAK,EAAE,uBAAuB,EAC9B,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,iCAAiC,EAC1C,gBAAgB,CAAC,EAAE,qBAAqB;YAa5B,sBAAsB;YAkBtB,kBAAkB;YAclB,qBAAqB;YAsDrB,eAAe;YAUf,SAAS;YAQT,qBAAqB;YAMrB,uBAAuB;IAerC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,WAAW;CAOpB"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "vona-module-image-native",
3
+ "version": "5.0.1",
4
+ "description": "",
5
+ "keywords": [
6
+ "Vona Module"
7
+ ],
8
+ "author": "",
9
+ "files": [
10
+ "dist",
11
+ "src"
12
+ ],
13
+ "type": "module",
14
+ "exports": {
15
+ ".": {
16
+ "types": [
17
+ "./src/index.ts",
18
+ "./dist/index.d.ts"
19
+ ],
20
+ "default": "./dist/index.js"
21
+ },
22
+ "./package.json": "./package.json"
23
+ },
24
+ "scripts": {
25
+ "clean": "rimraf dist tsconfig.build.tsbuildinfo",
26
+ "tsc:publish": "npm run clean && node ../../../../../packages-cli/cli/src/bin/vona.ts :bin:buildModule --sourcemap && tsc -p tsconfig.build.json",
27
+ "prepublishOnly": "npm run tsc:publish",
28
+ "prepack": "clean-package",
29
+ "postpack": "clean-package restore"
30
+ },
31
+ "dependencies": {
32
+ "sharp": "^0.35.2"
33
+ },
34
+ "devDependencies": {
35
+ "clean-package": "^2.2.0",
36
+ "rimraf": "^6.1.3"
37
+ },
38
+ "title": "image-native",
39
+ "vonaModule": {
40
+ "dependencies": {
41
+ "a-image": "5.0.0"
42
+ },
43
+ "globalDependencies": {
44
+ "sharp": true
45
+ },
46
+ "bundle": {
47
+ "externals": [
48
+ "sharp"
49
+ ]
50
+ },
51
+ "capabilities": {
52
+ "monkey": true
53
+ }
54
+ },
55
+ "gitHead": "7a711c5f09e0c1d3b0fda2084710297ea45b5d8e"
56
+ }
@@ -0,0 +1,114 @@
1
+ // eslint-disable
2
+ /** service: begin */
3
+ export * from '../service/imageNative.ts';
4
+
5
+ import 'vona-module-a-bean';
6
+ declare module 'vona-module-a-bean' {
7
+
8
+ export interface IServiceRecord {
9
+ 'image-native:imageNative': never;
10
+ }
11
+
12
+
13
+ }
14
+ declare module 'vona-module-image-native' {
15
+
16
+ export interface ServiceImageNative {
17
+ /** @internal */
18
+ get scope(): ScopeModuleImageNative;
19
+ }
20
+
21
+ export interface ServiceImageNative {
22
+ get $beanFullName(): 'image-native.service.imageNative';
23
+ get $onionName(): 'image-native:imageNative';
24
+
25
+ }
26
+ }
27
+ /** service: end */
28
+ /** service: begin */
29
+ import type { ServiceImageNative } from '../service/imageNative.ts';
30
+ export interface IModuleService {
31
+ 'imageNative': ServiceImageNative;
32
+ }
33
+ /** service: end */
34
+ /** service: begin */
35
+
36
+ import 'vona';
37
+ declare module 'vona' {
38
+ export interface IBeanRecordGeneral {
39
+ 'image-native.service.imageNative': ServiceImageNative;
40
+ }
41
+ }
42
+ /** service: end */
43
+ /** imageProvider: begin */
44
+ export * from '../bean/imageProvider.native.ts';
45
+ import type { IImageProviderOptionsNative } from '../bean/imageProvider.native.ts';
46
+ import 'vona-module-a-image';
47
+ declare module 'vona-module-a-image' {
48
+
49
+ export interface IImageProviderRecord {
50
+ 'image-native:native': IImageProviderOptionsNative;
51
+ }
52
+
53
+
54
+ }
55
+ declare module 'vona-module-image-native' {
56
+
57
+ export interface ImageProviderNative {
58
+ /** @internal */
59
+ get scope(): ScopeModuleImageNative;
60
+ }
61
+
62
+ export interface ImageProviderNative {
63
+ get $beanFullName(): 'image-native.imageProvider.native';
64
+ get $onionName(): 'image-native:native';
65
+ get $onionOptions(): IImageProviderOptionsNative;
66
+ }
67
+ }
68
+ /** imageProvider: end */
69
+ /** imageProvider: begin */
70
+ import type { ImageProviderNative } from '../bean/imageProvider.native.ts';
71
+ export interface IModuleImageProvider {
72
+ 'native': ImageProviderNative;
73
+ }
74
+ /** imageProvider: end */
75
+ /** config: begin */
76
+ export * from '../config/config.ts';
77
+ import type { config } from '../config/config.ts';
78
+ /** config: end */
79
+ /** monkey: begin */
80
+ export * from '../monkey.ts';
81
+ /** monkey: end */
82
+ /** scope: begin */
83
+ import { BeanScopeBase, type BeanScopeUtil, type TypeModuleConfig } from 'vona';
84
+ import { Scope } from 'vona-module-a-bean';
85
+
86
+ @Scope()
87
+ export class ScopeModuleImageNative extends BeanScopeBase {}
88
+
89
+ export interface ScopeModuleImageNative {
90
+ util: BeanScopeUtil;
91
+ config: TypeModuleConfig<typeof config>;
92
+ service: IModuleService;
93
+ imageProvider: IModuleImageProvider;
94
+ }
95
+
96
+ import 'vona';
97
+ declare module 'vona' {
98
+ export interface IBeanScopeRecord {
99
+ 'image-native': ScopeModuleImageNative;
100
+ }
101
+
102
+ export interface IBeanScopeContainer {
103
+ imageNative: ScopeModuleImageNative;
104
+ }
105
+
106
+ export interface IBeanScopeConfig {
107
+ 'image-native': ReturnType<typeof config>;
108
+ }
109
+
110
+
111
+
112
+
113
+ }
114
+ /** scope: end */
@@ -0,0 +1,2 @@
1
+ export const __ThisModule__ = 'image-native';
2
+ export { ScopeModuleImageNative as ScopeModule } from './index.ts';
@@ -0,0 +1,131 @@
1
+ import type {
2
+ IDecoratorImageProviderOptions,
3
+ IImageDeliveryOptions,
4
+ IImageDownloadResult,
5
+ IImageProviderClientOptions,
6
+ IImageProviderClientRecord,
7
+ IImageProviderExecute,
8
+ IImageProviderResource,
9
+ IImageUploadInput,
10
+ IImageVariantRequest,
11
+ } from 'vona-module-a-image';
12
+ import type { EntityImage } from 'vona-module-a-image';
13
+
14
+ import fse from 'fs-extra';
15
+ import { BeanBase } from 'vona';
16
+ import { ImageProvider } from 'vona-module-a-image';
17
+
18
+ export interface IImageProviderNativeClientRecord extends IImageProviderClientRecord {}
19
+
20
+ export interface IImageProviderNativeClientOptions extends IImageProviderClientOptions {
21
+ subdir?: string;
22
+ signingKey?: string;
23
+ tokenName?: string;
24
+ }
25
+
26
+ export interface IImageProviderOptionsNative extends IDecoratorImageProviderOptions<
27
+ IImageProviderNativeClientRecord,
28
+ IImageProviderNativeClientOptions
29
+ > {}
30
+
31
+ @ImageProvider<IImageProviderOptionsNative>({
32
+ base: {
33
+ subdir: 'default',
34
+ signedDeliveryKind: 'proxy',
35
+ },
36
+ })
37
+ export class ImageProviderNative extends BeanBase implements IImageProviderExecute {
38
+ async upload(
39
+ input: IImageUploadInput,
40
+ clientOptions: IImageProviderNativeClientOptions,
41
+ _options: IImageProviderOptionsNative,
42
+ ): Promise<IImageProviderResource> {
43
+ const resource = await this.scope.service.imageNative.upload(input, clientOptions);
44
+ return {
45
+ ...resource,
46
+ filename: input.filename,
47
+ contentType: input.contentType,
48
+ meta: input.meta,
49
+ };
50
+ }
51
+
52
+ async get(
53
+ image: EntityImage,
54
+ clientOptions: IImageProviderNativeClientOptions,
55
+ _options: IImageProviderOptionsNative,
56
+ ) {
57
+ return {
58
+ resourceId: image.resourceId,
59
+ filename: image.filename,
60
+ contentType: image.contentType,
61
+ size: image.size,
62
+ width: image.width,
63
+ height: image.height,
64
+ requireSignedURLs: image.requireSignedURLs,
65
+ variants: image.variants,
66
+ meta: image.meta,
67
+ storagePath: image.storagePath,
68
+ deliveryBaseUrl: image.deliveryBaseUrl ?? clientOptions.deliveryBaseUrl,
69
+ };
70
+ }
71
+
72
+ async delete(
73
+ image: EntityImage,
74
+ _clientOptions: IImageProviderClientOptions,
75
+ _options: IImageProviderOptionsNative,
76
+ ) {
77
+ await this.scope.service.imageNative.remove(image);
78
+ }
79
+
80
+ async getVariantUrl(
81
+ image: EntityImage,
82
+ request: IImageVariantRequest,
83
+ clientOptions: IImageProviderNativeClientOptions,
84
+ _options: IImageProviderOptionsNative,
85
+ deliveryOptions?: IImageDeliveryOptions,
86
+ ) {
87
+ return await this.scope.service.imageNative.getVariantUrl(
88
+ image,
89
+ request,
90
+ {
91
+ ...clientOptions,
92
+ subdir: clientOptions.subdir ?? 'default',
93
+ deliveryBaseUrl: image.deliveryBaseUrl ?? clientOptions.deliveryBaseUrl,
94
+ },
95
+ deliveryOptions,
96
+ );
97
+ }
98
+
99
+ async download(
100
+ image: EntityImage,
101
+ request: IImageVariantRequest,
102
+ clientOptions: IImageProviderNativeClientOptions,
103
+ options: IImageProviderOptionsNative,
104
+ deliveryOptions?: IImageDeliveryOptions,
105
+ ): Promise<IImageDownloadResult> {
106
+ if (
107
+ (deliveryOptions?.responseMode ?? 'auto') !== 'url' &&
108
+ !deliveryOptions?.signed &&
109
+ request.variantName === 'original' &&
110
+ !request.transformOptions
111
+ ) {
112
+ const buffer = image.storagePath ? await fse.readFile(image.storagePath) : undefined;
113
+ if (buffer) {
114
+ return {
115
+ kind: 'buffer',
116
+ buffer,
117
+ filename: image.filename,
118
+ contentType: image.contentType,
119
+ signed: false,
120
+ };
121
+ }
122
+ }
123
+ return {
124
+ kind: 'url',
125
+ url: await this.getVariantUrl(image, request, clientOptions, options, deliveryOptions),
126
+ filename: image.filename,
127
+ contentType: image.contentType,
128
+ signed: !!deliveryOptions?.signed,
129
+ };
130
+ }
131
+ }
@@ -0,0 +1,11 @@
1
+ import type { VonaApplication } from 'vona';
2
+
3
+ export function config(_app: VonaApplication) {
4
+ return {
5
+ imageNative: {
6
+ variants: {
7
+ original: {},
8
+ },
9
+ },
10
+ };
11
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './.metadata/index.ts';
package/src/monkey.ts ADDED
@@ -0,0 +1,33 @@
1
+ import type { IMonkeyAppStart } from 'vona';
2
+
3
+ import fse from 'fs-extra';
4
+ import path from 'node:path';
5
+ import { BeanSimple, cast, getPlatformArch, resolveAddon } from 'vona';
6
+
7
+ const __Version = '8.18.3';
8
+
9
+ const __MapTargetNames = {
10
+ 'linux-arm64': `libvips-cpp.so.${__Version}`,
11
+ 'linux-x64': `libvips-cpp.so.${__Version}`,
12
+ 'darwin-arm64': `libvips-cpp.${__Version}.dylib`,
13
+ 'darwin-x64': `libvips-cpp.${__Version}.dylib`,
14
+ 'win32-x64': 'libvips-42.dll',
15
+ };
16
+
17
+ export class Monkey extends BeanSimple implements IMonkeyAppStart {
18
+ async appStart() {
19
+ cast(this.app).__prepareSharpLibvips = () => {
20
+ const platformArch = getPlatformArch();
21
+ const addonFileSrc = resolveAddon('sharpLibvips');
22
+ const addonDirDest = path.join(
23
+ import.meta.dirname,
24
+ `node_modules/@img/sharp-libvips-${platformArch}/lib`,
25
+ );
26
+ const addonFileDest = path.join(addonDirDest, __MapTargetNames[platformArch]);
27
+ if (!fse.existsSync(addonFileDest)) {
28
+ fse.ensureDirSync(addonDirDest);
29
+ fse.copyFileSync(addonFileSrc, addonFileDest);
30
+ }
31
+ };
32
+ }
33
+ }
@@ -0,0 +1,291 @@
1
+ import type { SharpConstructor } from 'sharp';
2
+ import type {
3
+ EntityImage,
4
+ IImageDeliveryOptions,
5
+ IImageNamedVariants,
6
+ IImageProviderResolvedVariant,
7
+ IImageProviderResource,
8
+ IImageTransformOptions,
9
+ IImageUploadInput,
10
+ IImageVariantRequest,
11
+ } from 'vona-module-a-image';
12
+
13
+ import fse from 'fs-extra';
14
+ import { createHash } from 'node:crypto';
15
+ import path from 'node:path';
16
+ import { BeanBase, uuidv4 } from 'vona';
17
+ import { Service } from 'vona-module-a-bean';
18
+ import { resolveImageVariantRequestToTransform } from 'vona-module-a-image';
19
+
20
+ import type { IImageProviderNativeClientOptions } from '../bean/imageProvider.native.ts';
21
+
22
+ type IImageNativeStoredImage = Pick<
23
+ EntityImage,
24
+ 'resourceId' | 'filename' | 'storagePath' | 'variants'
25
+ >;
26
+
27
+ @Service()
28
+ export class ServiceImageNative extends BeanBase {
29
+ private _sharpInstance: SharpConstructor;
30
+
31
+ private async getSharp() {
32
+ if (!this._sharpInstance) {
33
+ this._sharpInstance = (await import('sharp')).default;
34
+ }
35
+ return this._sharpInstance;
36
+ }
37
+
38
+ async upload(
39
+ input: IImageUploadInput,
40
+ options: IImageProviderNativeClientOptions,
41
+ ): Promise<IImageProviderResource> {
42
+ const publicPath = await this.app.util.getPublicPathPhysical(
43
+ path.join('image-native', options.subdir ?? 'default'),
44
+ true,
45
+ );
46
+ const resourceId = uuidv4();
47
+ const ext = this._getOriginalExt(input.filename, input.file);
48
+ const targetName = `${resourceId}${ext}`;
49
+ const targetPath = path.join(publicPath, targetName);
50
+ await fse.copy(input.file, targetPath);
51
+ const sharp = await this.getSharp();
52
+ const metadata = await sharp(targetPath).metadata();
53
+ const stat = await fse.stat(targetPath);
54
+ const variants = options.variants ?? this.scope.config.imageNative.variants;
55
+ await this._generateNamedVariants(
56
+ { resourceId, filename: input.filename, storagePath: targetPath, variants },
57
+ options,
58
+ );
59
+ return {
60
+ resourceId,
61
+ size: Number(stat.size),
62
+ width: metadata.width,
63
+ height: metadata.height,
64
+ storagePath: targetPath,
65
+ deliveryBaseUrl: options.deliveryBaseUrl,
66
+ requireSignedURLs: input.requireSignedURLs ?? options.requireSignedURLs,
67
+ variants,
68
+ };
69
+ }
70
+
71
+ async remove(image: IImageNativeStoredImage) {
72
+ if (!image.storagePath) return;
73
+ const dir = path.dirname(image.storagePath);
74
+ if (!(await fse.pathExists(dir))) return;
75
+ const entries = await fse.readdir(dir);
76
+ await Promise.all(
77
+ entries
78
+ .filter(
79
+ name =>
80
+ name === path.basename(image.storagePath!) || name.startsWith(`${image.resourceId}__`),
81
+ )
82
+ .map(name => fse.remove(path.join(dir, name))),
83
+ );
84
+ }
85
+
86
+ async getVariantUrl(
87
+ image: IImageNativeStoredImage,
88
+ request: IImageVariantRequest,
89
+ options: IImageProviderNativeClientOptions,
90
+ _deliveryOptions?: IImageDeliveryOptions,
91
+ ) {
92
+ const resolved = resolveImageVariantRequestToTransform(request, 'original', image.variants);
93
+ if (
94
+ resolved.variantName === 'original' &&
95
+ this._isOriginalTransform(resolved.transformOptions)
96
+ ) {
97
+ return await this._getOriginalUrl(image, options);
98
+ }
99
+ const targetPath = await this._ensureVariantFile(image, resolved);
100
+ return await this._buildUrl(targetPath, options.deliveryBaseUrl);
101
+ }
102
+
103
+ private async _generateNamedVariants(
104
+ image: IImageNativeStoredImage,
105
+ options: IImageProviderNativeClientOptions,
106
+ ) {
107
+ const variantNames = Object.keys(image.variants ?? {}) as Array<
108
+ keyof NonNullable<IImageNamedVariants>
109
+ >;
110
+ for (const variantName of variantNames) {
111
+ if (variantName === 'original') continue;
112
+ await this._ensureVariantFile(
113
+ image,
114
+ resolveImageVariantRequestToTransform({ variantName }, 'original', image.variants),
115
+ );
116
+ }
117
+ if (!image.variants?.original) return;
118
+ await this.getVariantUrl(image, { variantName: 'original' }, options);
119
+ }
120
+
121
+ private async _ensureVariantFile(
122
+ image: IImageNativeStoredImage,
123
+ resolved: IImageProviderResolvedVariant,
124
+ ) {
125
+ if (!image.storagePath) {
126
+ throw new Error(`Image storage path missing: ${image.resourceId}`);
127
+ }
128
+ const targetPath = await this._getVariantAbsolutePath(image, resolved);
129
+ if (!(await fse.pathExists(targetPath))) {
130
+ await this._writeTransformedFile(image.storagePath, targetPath, resolved.transformOptions);
131
+ }
132
+ return targetPath;
133
+ }
134
+
135
+ private async _writeTransformedFile(
136
+ sourcePath: string,
137
+ targetPath: string,
138
+ transformOptions: IImageTransformOptions,
139
+ ) {
140
+ await fse.ensureDir(path.dirname(targetPath));
141
+ if (this._isOriginalTransform(transformOptions)) {
142
+ await fse.copy(sourcePath, targetPath, { overwrite: true });
143
+ return;
144
+ }
145
+ const sharp = await this.getSharp();
146
+ let pipeline = sharp(sourcePath, { failOn: 'none' });
147
+ const width =
148
+ transformOptions.width && transformOptions.dpr
149
+ ? Math.round(transformOptions.width * transformOptions.dpr)
150
+ : transformOptions.width;
151
+ const height =
152
+ transformOptions.height && transformOptions.dpr
153
+ ? Math.round(transformOptions.height * transformOptions.dpr)
154
+ : transformOptions.height;
155
+ if (
156
+ width ||
157
+ height ||
158
+ transformOptions.fit ||
159
+ transformOptions.gravity ||
160
+ transformOptions.background
161
+ ) {
162
+ pipeline = pipeline.resize({
163
+ width,
164
+ height,
165
+ fit: this._mapFit(transformOptions.fit),
166
+ position: this._mapGravity(transformOptions.gravity),
167
+ background: transformOptions.background,
168
+ });
169
+ }
170
+ if (transformOptions.rotate !== undefined) {
171
+ pipeline = pipeline.rotate(transformOptions.rotate);
172
+ }
173
+ if (transformOptions.sharpen !== undefined) {
174
+ pipeline = pipeline.sharpen({ sigma: transformOptions.sharpen });
175
+ }
176
+ const format = this._normalizeFormat(transformOptions.format);
177
+ if (format === 'jpeg') {
178
+ pipeline = pipeline.jpeg({ quality: transformOptions.quality });
179
+ } else if (format === 'png') {
180
+ pipeline = pipeline.png({ quality: transformOptions.quality });
181
+ } else if (format === 'webp') {
182
+ pipeline = pipeline.webp({ quality: transformOptions.quality });
183
+ } else if (format === 'avif') {
184
+ pipeline = pipeline.avif({ quality: transformOptions.quality });
185
+ }
186
+ await pipeline.toFile(targetPath);
187
+ }
188
+
189
+ private async _getOriginalUrl(
190
+ image: IImageNativeStoredImage,
191
+ options: IImageProviderNativeClientOptions,
192
+ ) {
193
+ if (!image.storagePath) {
194
+ throw new Error(`Image storage path missing: ${image.resourceId}`);
195
+ }
196
+ return await this._buildUrl(image.storagePath, options.deliveryBaseUrl);
197
+ }
198
+
199
+ private async _buildUrl(targetPath: string, deliveryBaseUrl?: string) {
200
+ const variantPath = await this._getVariantStaticPath(targetPath);
201
+ if (deliveryBaseUrl) {
202
+ return `${deliveryBaseUrl.replace(/\/$/, '')}/${variantPath}`;
203
+ }
204
+ return this.app.util.combineStaticPath(`/${variantPath}`);
205
+ }
206
+
207
+ private async _getVariantStaticPath(targetPath: string) {
208
+ const publicRoot = await this.app.util.getPublicPathPhysical(undefined, true);
209
+ const relativePath = path.relative(publicRoot, targetPath).split(path.sep).join(path.posix.sep);
210
+ return path.posix.join('public', this.ctx.instance.id.toString(), relativePath);
211
+ }
212
+
213
+ private async _getVariantAbsolutePath(
214
+ image: IImageNativeStoredImage,
215
+ resolved: IImageProviderResolvedVariant,
216
+ ) {
217
+ if (!image.storagePath) throw new Error(`Image storage path missing: ${image.resourceId}`);
218
+ const dir = path.dirname(image.storagePath);
219
+ const ext = this._getVariantExt(image.filename, image.storagePath, resolved.transformOptions);
220
+ if (resolved.variantName !== 'custom') {
221
+ const variantName = this._sanitizeVariantName(resolved.variantName);
222
+ return path.join(dir, `${image.resourceId}__${variantName}${ext}`);
223
+ }
224
+ const cacheKey = this._buildTransformCacheKey(resolved.transformOptions);
225
+ return path.join(dir, `${image.resourceId}__t_${cacheKey}${ext}`);
226
+ }
227
+
228
+ private _getVariantExt(
229
+ filename: string | undefined,
230
+ storagePath: string | undefined,
231
+ transformOptions: IImageTransformOptions,
232
+ ) {
233
+ const format = this._normalizeFormat(transformOptions.format);
234
+ if (format) {
235
+ return format === 'jpeg' ? '.jpg' : `.${format}`;
236
+ }
237
+ return path.extname(filename ?? '') || path.extname(storagePath ?? '') || '.bin';
238
+ }
239
+
240
+ private _getOriginalExt(filename: string | undefined, filePath: string) {
241
+ return path.extname(filename ?? '') || path.extname(filePath) || '.bin';
242
+ }
243
+
244
+ private _normalizeFormat(format: IImageTransformOptions['format']) {
245
+ if (!format || format === 'auto') return undefined;
246
+ return format === 'jpeg' ? 'jpeg' : format;
247
+ }
248
+
249
+ private _buildTransformCacheKey(transformOptions: IImageTransformOptions) {
250
+ const stable = this._stableStringify(transformOptions);
251
+ return createHash('sha1').update(stable).digest('hex').slice(0, 12);
252
+ }
253
+
254
+ private _stableStringify(value: unknown): string {
255
+ if (Array.isArray(value)) {
256
+ return `[${value.map(item => this._stableStringify(item)).join(',')}]`;
257
+ }
258
+ if (value && typeof value === 'object') {
259
+ const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>
260
+ a.localeCompare(b),
261
+ );
262
+ return `{${entries
263
+ .map(([key, item]) => `${JSON.stringify(key)}:${this._stableStringify(item)}`)
264
+ .join(',')}}`;
265
+ }
266
+ return JSON.stringify(value);
267
+ }
268
+
269
+ private _sanitizeVariantName(variantName: string) {
270
+ return variantName.replace(/[^\w.-]/g, '-');
271
+ }
272
+
273
+ private _isOriginalTransform(transformOptions: IImageTransformOptions) {
274
+ return Object.keys(transformOptions).length === 0;
275
+ }
276
+
277
+ private _mapFit(fit: IImageTransformOptions['fit']) {
278
+ if (fit === 'scale-down') return 'inside' as const;
279
+ if (fit === 'contain' || fit === 'pad') return 'contain' as const;
280
+ if (fit === 'cover' || fit === 'crop') return 'cover' as const;
281
+ return undefined;
282
+ }
283
+
284
+ private _mapGravity(gravity: IImageTransformOptions['gravity']) {
285
+ if (gravity === 'top') return 'north';
286
+ if (gravity === 'bottom') return 'south';
287
+ if (gravity === 'left') return 'west';
288
+ if (gravity === 'right') return 'east';
289
+ return 'centre';
290
+ }
291
+ }