pg-mvc-service 2.1.0 → 2.1.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.
Files changed (95) hide show
  1. package/dist/PoolManager.d.ts +7 -0
  2. package/dist/PoolManager.d.ts.map +1 -0
  3. package/dist/Service.d.ts +82 -0
  4. package/dist/Service.d.ts.map +1 -0
  5. package/dist/Utils/DateTimeUtil.d.ts +58 -0
  6. package/dist/Utils/DateTimeUtil.d.ts.map +1 -0
  7. package/dist/Utils/NumberUtil.d.ts +10 -0
  8. package/dist/Utils/NumberUtil.d.ts.map +1 -0
  9. package/dist/Utils/StringUtil.d.ts +16 -0
  10. package/dist/Utils/StringUtil.d.ts.map +1 -0
  11. package/dist/clients/AwsS3Client.d.ts +35 -0
  12. package/dist/clients/AwsS3Client.d.ts.map +1 -0
  13. package/dist/clients/Base64Client.d.ts +31 -0
  14. package/dist/clients/Base64Client.d.ts.map +1 -0
  15. package/dist/clients/EncryptClient.d.ts +18 -0
  16. package/dist/clients/EncryptClient.d.ts.map +1 -0
  17. package/dist/clients/StringClient.d.ts +6 -0
  18. package/dist/clients/StringClient.d.ts.map +1 -0
  19. package/dist/cron/BaseCron.d.ts +35 -0
  20. package/dist/cron/BaseCron.d.ts.map +1 -0
  21. package/dist/cron/CronExecuter.d.ts +2 -0
  22. package/dist/cron/CronExecuter.d.ts.map +1 -0
  23. package/dist/cron/CronType.d.ts +6 -0
  24. package/dist/cron/CronType.d.ts.map +1 -0
  25. package/dist/documents/Swagger.d.ts +10 -0
  26. package/dist/documents/Swagger.d.ts.map +1 -0
  27. package/dist/exceptions/Exception.d.ts +31 -0
  28. package/dist/exceptions/Exception.d.ts.map +1 -0
  29. package/{src/index.ts → dist/index.d.ts} +2 -6
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/models/ExpressionClient.d.ts +12 -0
  32. package/dist/models/ExpressionClient.d.ts.map +1 -0
  33. package/dist/models/MigrateDatabase.d.ts +19 -0
  34. package/dist/models/MigrateDatabase.d.ts.map +1 -0
  35. package/dist/models/MigrateRollback.d.ts +18 -0
  36. package/dist/models/MigrateRollback.d.ts.map +1 -0
  37. package/dist/models/MigrateTable.d.ts +13 -0
  38. package/dist/models/MigrateTable.d.ts.map +1 -0
  39. package/dist/models/SqlUtils/SelectExpression.d.ts +31 -0
  40. package/dist/models/SqlUtils/SelectExpression.d.ts.map +1 -0
  41. package/dist/models/SqlUtils/UpdateExpression.d.ts +8 -0
  42. package/dist/models/SqlUtils/UpdateExpression.d.ts.map +1 -0
  43. package/dist/models/SqlUtils/ValidateValueUtil.d.ts +19 -0
  44. package/dist/models/SqlUtils/ValidateValueUtil.d.ts.map +1 -0
  45. package/dist/models/SqlUtils/WhereExpression.d.ts +30 -0
  46. package/dist/models/SqlUtils/WhereExpression.d.ts.map +1 -0
  47. package/dist/models/TableDoc.d.ts +3 -0
  48. package/dist/models/TableDoc.d.ts.map +1 -0
  49. package/dist/models/TableModel.d.ts +196 -0
  50. package/dist/models/TableModel.d.ts.map +1 -0
  51. package/dist/models/Type.d.ts +64 -0
  52. package/dist/models/Type.d.ts.map +1 -0
  53. package/dist/models/Utils/MessageUtil.d.ts +7 -0
  54. package/dist/models/Utils/MessageUtil.d.ts.map +1 -0
  55. package/dist/models/ValidateClient.d.ts +27 -0
  56. package/dist/models/ValidateClient.d.ts.map +1 -0
  57. package/dist/reqestResponse/ReqResType.d.ts +113 -0
  58. package/dist/reqestResponse/ReqResType.d.ts.map +1 -0
  59. package/dist/reqestResponse/RequestType.d.ts +247 -0
  60. package/dist/reqestResponse/RequestType.d.ts.map +1 -0
  61. package/dist/reqestResponse/ResponseType.d.ts +85 -0
  62. package/dist/reqestResponse/ResponseType.d.ts.map +1 -0
  63. package/package.json +7 -1
  64. package/index.d.ts +0 -192
  65. package/src/PoolManager.ts +0 -48
  66. package/src/Service.ts +0 -307
  67. package/src/Utils/DateTimeUtil.ts +0 -146
  68. package/src/Utils/NumberUtil.ts +0 -23
  69. package/src/Utils/StringUtil.ts +0 -33
  70. package/src/clients/AwsS3Client.ts +0 -310
  71. package/src/clients/Base64Client.ts +0 -305
  72. package/src/clients/EncryptClient.ts +0 -100
  73. package/src/clients/StringClient.ts +0 -19
  74. package/src/cron/BaseCron.ts +0 -122
  75. package/src/cron/CronExecuter.ts +0 -34
  76. package/src/cron/CronType.ts +0 -25
  77. package/src/documents/Swagger.ts +0 -106
  78. package/src/exceptions/Exception.ts +0 -72
  79. package/src/models/ExpressionClient.ts +0 -72
  80. package/src/models/MigrateDatabase.ts +0 -135
  81. package/src/models/MigrateRollback.ts +0 -151
  82. package/src/models/MigrateTable.ts +0 -56
  83. package/src/models/SqlUtils/SelectExpression.ts +0 -102
  84. package/src/models/SqlUtils/UpdateExpression.ts +0 -29
  85. package/src/models/SqlUtils/ValidateValueUtil.ts +0 -354
  86. package/src/models/SqlUtils/WhereExpression.ts +0 -455
  87. package/src/models/TableDoc.ts +0 -372
  88. package/src/models/TableModel.ts +0 -749
  89. package/src/models/Type.ts +0 -62
  90. package/src/models/Utils/MessageUtil.ts +0 -60
  91. package/src/models/ValidateClient.ts +0 -182
  92. package/src/reqestResponse/ReqResType.ts +0 -241
  93. package/src/reqestResponse/RequestType.ts +0 -1619
  94. package/src/reqestResponse/ResponseType.ts +0 -549
  95. package/tsconfig.json +0 -14
@@ -1,310 +0,0 @@
1
- import { _Object, DeleteObjectsCommand, GetObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client, ScanRange } from '@aws-sdk/client-s3';
2
- import { Base64Client } from './Base64Client';
3
- import { UnprocessableException } from '../exceptions/Exception';
4
- import axios from 'axios';
5
-
6
- type IUploadResponse = {
7
- url: string;
8
- fileName: string;
9
- }
10
-
11
- export class AwsS3Client {
12
- private client: S3Client;
13
-
14
- private readonly bucketName;
15
- private readonly region;
16
- get UrlPrefix(): string {
17
- return `https://${this.bucketName}.s3.${this.region}.amazonaws.com`;
18
- }
19
-
20
- constructor(params: {bucketName?: string, region?: string; accessKeyId?: string, secretAccessKey?: string}) {
21
- if (params.bucketName === undefined) {
22
- throw new Error("Please specify the bucketName.");
23
- }
24
-
25
- if (params.region === undefined) {
26
- throw new Error("Please specify the region.");
27
- }
28
-
29
- if (params.accessKeyId === undefined) {
30
- throw new Error("Please specify the accessKeyId.");
31
- }
32
-
33
- if (params.secretAccessKey === undefined) {
34
- throw new Error("Please specify the secretAccessKey.");
35
- }
36
-
37
- this.client = new S3Client({
38
- region: params.region,
39
- credentials: {
40
- accessKeyId: params.accessKeyId,
41
- secretAccessKey: params.secretAccessKey
42
- }
43
- });
44
-
45
- this.region = params.region;
46
- this.bucketName = params.bucketName;
47
- }
48
-
49
- private makeKey(path: string, fileName?: string): string {
50
- path = path.replace(/^\/|\/$/g, '');
51
- if ((fileName ?? '').trim().length > 0) {
52
- path += '/' + fileName;
53
- }
54
- return path;
55
- }
56
-
57
- public url(path: string, fileName: string = '') {
58
- path = path.replace(/^\/|\/$/g, '');
59
- let url = `${this.UrlPrefix}`;
60
- if (path !== '') {
61
- url += '/' + path;
62
- }
63
-
64
- if (fileName.trim().length > 0) {
65
- url += '/' + fileName;
66
- }
67
- return url;
68
- }
69
-
70
- public async uploadJson(path: string, fileName: string, data: {[key: string]: any}) {
71
- const command = new PutObjectCommand({
72
- Bucket: this.bucketName,
73
- Key: this.makeKey(path, fileName),
74
- Body: JSON.stringify(data),
75
- ContentType: 'text/plain; charset=utf-8'
76
- });
77
- await this.client.send(command);
78
- }
79
-
80
- public async uploadToPdf(path: string, fileName: string, base64Datas: Array<string>) {
81
- const base64Client = new Base64Client();
82
- const mergedPdfBase64 = await base64Client.mergeToPdfBase64(base64Datas);
83
-
84
- const command = new PutObjectCommand({
85
- Bucket: this.bucketName,
86
- Key: this.makeKey(path, fileName),
87
- Body: Buffer.from(mergedPdfBase64, 'base64'),
88
- ContentEncoding: 'base64',
89
- ContentType: 'application/pdf'
90
- });
91
- await this.client.send(command);
92
- }
93
-
94
- public async uploadText(path: string, fileName: string, text: string) {
95
- const command = new PutObjectCommand({
96
- Bucket: this.bucketName,
97
- Key: this.makeKey(path, fileName),
98
- Body: text,
99
- ContentType: 'text/plain; charset=utf-8'
100
- });
101
- await this.client.send(command);
102
- }
103
-
104
- public async uploadBase64Data(path: string, fileName: string, base64Data: string) : Promise<IUploadResponse> {
105
- const base64Client = new Base64Client();
106
-
107
- const type = base64Client.getMimeType(base64Data);
108
- const extension = {
109
- 'image/png': '.png',
110
- 'image/jpeg': '.jpeg',
111
- 'image/gif': '.gif',
112
- 'application/pdf': '.pdf'
113
- }[type];
114
- if (fileName.endsWith(extension) === false) {
115
- fileName += extension;
116
- }
117
-
118
- const key = this.makeKey(path, fileName);
119
- const command = new PutObjectCommand({
120
- Bucket: this.bucketName,
121
- Key: key,
122
- Body: Buffer.from(base64Data, 'base64'),
123
- ContentEncoding: 'base64',
124
- ContentType: type
125
- });
126
- await this.client.send(command);
127
-
128
- return {
129
- url: `${this.UrlPrefix}/${key}`,
130
- fileName: fileName
131
- }
132
- }
133
-
134
- public async uploadFromUrl(path: string, fileName: string, url: string): Promise<IUploadResponse> {
135
- try {
136
- // URLからデータを取得
137
- const response = await axios.get(url, {
138
- responseType: 'arraybuffer',
139
- timeout: 30000,
140
- });
141
-
142
- // Content-Typeを取得
143
- const contentType = response.headers['content-type'] || 'application/octet-stream';
144
-
145
- const key = this.makeKey(path, fileName);
146
- const command = new PutObjectCommand({
147
- Bucket: this.bucketName,
148
- Key: key,
149
- Body: Buffer.from(response.data),
150
- ContentType: contentType,
151
- ContentLength: response.data.length
152
- });
153
-
154
- await this.client.send(command);
155
-
156
- // アップロードされたファイルのURLを返す
157
- return {
158
- url: this.url(path, fileName),
159
- fileName: fileName
160
- }
161
- } catch (error) {
162
- if (axios.isAxiosError(error)) {
163
- if (error.response) {
164
- throw new UnprocessableException(`Failed to download from URL. HTTP ${error.response.status}: ${error.response.statusText}`);
165
- } else if (error.request) {
166
- throw new UnprocessableException('Failed to connect to the URL. Please check if the URL is accessible.');
167
- } else {
168
- throw new UnprocessableException('Invalid URL format.');
169
- }
170
- }
171
- throw new UnprocessableException('Failed to upload from URL.');
172
- }
173
- }
174
-
175
- public async uploadStackText(path: string, fileName: string, text: string) {
176
- let preText = await this.getText(path, fileName);
177
- if (typeof preText === 'string') {
178
- text = preText + '\n' + text;
179
- }
180
-
181
- await this.uploadText(path, fileName, text);
182
- }
183
-
184
- public async getText(path: string, fileName: string) : Promise<string | null> {
185
- try {
186
- const command = new GetObjectCommand({
187
- Bucket: this.bucketName,
188
- Key: this.makeKey(path, fileName),
189
- });
190
- const res = await this.client.send(command);
191
-
192
- if (res.Body === undefined) {
193
- throw new Error(`Failed to get text data. Response body is undefined.`);
194
- }
195
-
196
- if (res.ContentType?.startsWith('text/') === false) {
197
- throw new Error(`Cannot get text data from non-text file. ContentType: ${res.ContentType}`);
198
- }
199
-
200
- // v3ではBodyがReadableStreamなので、変換が必要
201
- const chunks: Uint8Array[] = [];
202
- if (res.Body && typeof res.Body === 'object' && 'getReader' in res.Body) {
203
- // ReadableStreamの場合
204
- const stream = res.Body as ReadableStream;
205
- const reader = stream.getReader();
206
-
207
- while (true) {
208
- const { done, value } = await reader.read();
209
- if (done) break;
210
- chunks.push(value);
211
- }
212
- } else {
213
- // Node.js Readableの場合
214
- for await (const chunk of res.Body as any) {
215
- chunks.push(chunk);
216
- }
217
- }
218
-
219
- const buffer = Buffer.concat(chunks);
220
- return buffer.toString('utf-8');
221
- } catch (ex: unknown) {
222
- if (ex instanceof Error && ex.name === 'NoSuchKey') {
223
- return null;
224
- }
225
- throw ex;
226
- }
227
- }
228
-
229
- public async getFilesInDir(path: string): Promise<Array<_Object>> {
230
- const listCommand = new ListObjectsV2Command({
231
- Bucket: this.bucketName,
232
- Prefix: this.makeKey(path),
233
- });
234
-
235
- const data = await this.client.send(listCommand);
236
- return data.Contents ?? [];
237
- }
238
-
239
- public async getDataFronJson<T = any>(path: string, fileName: string): Promise<T> {
240
- const command = new GetObjectCommand({
241
- Bucket: this.bucketName,
242
- Key: this.makeKey(path, fileName),
243
- });
244
- const res = await this.client.send(command);
245
-
246
- if (res.Body === undefined) {
247
- throw new Error(`Failed to get JSON data. Response body is undefined.`);
248
- }
249
-
250
- if (res.ContentType !== 'application/json') {
251
- throw new Error(`Cannot get JSON data from non-JSON file. ContentType: ${res.ContentType}`);
252
- }
253
-
254
- // v3ではBodyがReadableなので、変換が必要
255
- const chunks: Uint8Array[] = [];
256
- for await (const chunk of res.Body as any) {
257
- chunks.push(chunk);
258
- }
259
-
260
- const buffer = Buffer.concat(chunks);
261
- const jsonString = buffer.toString('utf-8');
262
- return JSON.parse(jsonString) as T;
263
- }
264
-
265
- public async deleteFile(path: string, fileName: string): Promise<void> {
266
- const key = this.makeKey(path, fileName);
267
- const command = new DeleteObjectsCommand({
268
- Bucket: this.bucketName,
269
- Delete: {
270
- Objects: [{ Key: key }]
271
- }
272
- });
273
- await this.client.send(command);
274
- }
275
-
276
- public async deleteDir(path: string): Promise<void> {
277
- const files = await this.getFilesInDir(path);
278
- if (files.length > 0) {
279
- const deleteCommand = new DeleteObjectsCommand({
280
- Bucket: this.bucketName,
281
- Delete: {
282
- Objects: files.map((file) => ({ Key: file.Key })),
283
- },
284
- });
285
- await this.client.send(deleteCommand);
286
- }
287
- }
288
-
289
- public async deleteFromUrl(url: string, isFileUrl: boolean = true): Promise<void> {
290
- const path = url.replace(this.UrlPrefix + '/', '');
291
- if (url === path) {
292
- throw new UnprocessableException('The specified URL cannot be deleted because the bucket and region do not match.');
293
- }
294
-
295
- if (path.trim() === "") {
296
- throw new UnprocessableException('This URL is invalid.');
297
- }
298
-
299
- if (isFileUrl) {
300
- const pathSplits = path.split('/');
301
- const file = pathSplits.pop();
302
- if (file === undefined) {
303
- throw new UnprocessableException('This URL is invalid.');
304
- }
305
- await this.deleteFile(pathSplits.join('/'), file);
306
- } else {
307
- await this.deleteDir(path);
308
- }
309
- }
310
- }
@@ -1,305 +0,0 @@
1
- import axios from 'axios';
2
- import { PDFDocument } from 'pdf-lib';
3
- import sharp from 'sharp';
4
- import { ValidateStringUtil } from 'type-utils-n-daira';
5
-
6
- export type TPng = 'image/png';
7
- export type TJpeg = 'image/jpeg';
8
- export type TGif = 'image/gif';
9
- export type TImage = TPng | TJpeg | TGif;
10
-
11
- export type TPdf = 'application/pdf';
12
- export type TJson = 'application/json';
13
-
14
- export class Base64Client {
15
- public readonly PREFIX_JPEG_DATA = '/9j/';
16
- public readonly PREFIX_PNG_DATA = 'iVBORw0KGgo';
17
-
18
- constructor() { }
19
-
20
- // public encode(text: string): string {
21
- // return Buffer.from(text).toString('base64');
22
- // }
23
-
24
- public tryDecode(base64: string): Buffer | false {
25
- try {
26
- // Data URLのパターンをチェック
27
- if (base64.startsWith('data:')) {
28
- const matches = base64.match(/^data:([A-Za-z-+/]+);base64,(.+)$/);
29
- if (!matches || matches.length !== 3) {
30
- return false;
31
- }
32
- // base64部分のみを取得
33
- base64 = matches[2];
34
- }
35
-
36
- if (base64.length % 4 !== 0) {
37
- return false;
38
- }
39
-
40
- const regex = /^[A-Za-z0-9+/]*={0,2}$/;
41
- if (!regex.test(base64)) {
42
- return false;
43
- }
44
-
45
- return Buffer.from(base64, 'base64');
46
- } catch {
47
- return false;
48
- }
49
- }
50
-
51
- public getMimeType(data: string | Buffer): TImage | TPdf {
52
- try {
53
- let buffer;
54
- if (typeof data === 'string') {
55
- // Data URLのパターンをチェック
56
- if (data.startsWith('data:')) {
57
- const matches = data.match(/^data:([A-Za-z-+/]+);base64,(.+)$/);
58
- if (!matches || matches.length !== 3) {
59
- throw new Error('Invalid Data URL format');
60
- }
61
- // base64部分のみを取得
62
- data = matches[2];
63
- }
64
- buffer = this.tryDecode(data);
65
- } else {
66
- buffer = data;
67
- }
68
-
69
- if (buffer === false) {
70
- throw new Error('Cannot getMineType because the input is not in base64 format.');
71
- }
72
-
73
- const header = buffer.subarray(0, 4);
74
- if (header[0] === 0x25 && header[1] === 0x50 && header[2] === 0x44 && header[3] === 0x46) {
75
- return 'application/pdf';
76
- } else if (header[0] === 0x89 && header[1] === 0x50 && header[2] === 0x4E && header[3] === 0x47) {
77
- return 'image/png';
78
- } else if (header[0] === 0xFF && header[1] === 0xD8) {
79
- return 'image/jpeg';
80
- } else if (header[0] === 0x47 && header[1] === 0x49 && header[2] === 0x46 && header[3] === 0x38) {
81
- return 'image/gif';
82
- }
83
-
84
- throw new Error('Cannot getMimeType because the file type is not PDF, PNG, JPEG, or GIF.');
85
- } catch {
86
- throw new Error('Cannot getMineType because the input is not in base64 format.');
87
- }
88
- }
89
-
90
- public async mergeToPdfBase64(datas: string[]): Promise<string> {
91
- const mergedPdf = await PDFDocument.create();
92
-
93
- for (const data of datas) {
94
- const buffer = this.tryDecode(data);
95
- if (buffer === false) {
96
- throw new Error('Cannot mergeToPdf because the input is not in base64 format.');
97
- }
98
-
99
- const fileType = this.getMimeType(buffer);
100
- if (fileType === 'application/pdf') {
101
- const pdfDoc = await PDFDocument.load(buffer);
102
- const pages = await mergedPdf.copyPages(pdfDoc, pdfDoc.getPageIndices());
103
- pages.forEach(page => mergedPdf.addPage(page));
104
- } else {
105
- // convert from image to pdf
106
- const imagePdf = await this.convertImageToPdf(buffer);
107
- const pdfDoc = await PDFDocument.load(imagePdf);
108
- const pages = await mergedPdf.copyPages(pdfDoc, pdfDoc.getPageIndices());
109
- pages.forEach(page => mergedPdf.addPage(page));
110
- }
111
- }
112
-
113
- // 結合したPDFをBase64に変換
114
- const mergedPdfBytes = await mergedPdf.save();
115
- return Buffer.from(mergedPdfBytes).toString('base64');
116
- }
117
-
118
- private async convertImageToPdf(imageBuffer: Buffer): Promise<Buffer> {
119
- const fileType = this.getMimeType(imageBuffer);
120
-
121
- let optimizedImage;
122
- if (fileType === 'image/gif') {
123
- // gifの場合はpngに変換して処理
124
- optimizedImage = await sharp(imageBuffer)
125
- .png()
126
- .toBuffer();
127
- } else {
128
- optimizedImage = await sharp(imageBuffer).toBuffer();
129
- }
130
-
131
- // 新しいPDFドキュメントを作成
132
- const pdfDoc = await PDFDocument.create();
133
- const page = pdfDoc.addPage();
134
-
135
- // 画像をPDFに埋め込み
136
-
137
- let image;
138
- if (fileType === 'image/jpeg') {
139
- image = await pdfDoc.embedJpg(optimizedImage);
140
- } else {
141
- image = await pdfDoc.embedPng(optimizedImage);
142
- }
143
- const { width, height } = image.scale(1);
144
-
145
- // ページサイズを画像に合わせる
146
- page.setSize(width, height);
147
-
148
- // 画像を描画
149
- page.drawImage(image, {
150
- x: 0,
151
- y: 0,
152
- width,
153
- height,
154
- });
155
-
156
- // PDFをバッファに変換
157
- const pdfBytes = await pdfDoc.save();
158
- return Buffer.from(pdfBytes);
159
- }
160
-
161
- public isJpeg(value: any): value is string {
162
- if (ValidateStringUtil.isBase64(value) === false) {
163
- return false
164
- }
165
-
166
- if (value.startsWith('data:')) {
167
- if (value.startsWith('data:image/jpeg,') === false && value.startsWith('data:image/jpg,') === false) {
168
- return false;
169
- }
170
-
171
- const valueParts = value.split(',');
172
- if (valueParts.length !== 2) {
173
- return false;
174
- }
175
-
176
- return valueParts[1].startsWith(this.PREFIX_JPEG_DATA);
177
- }
178
-
179
- return value.startsWith(this.PREFIX_JPEG_DATA);
180
- }
181
-
182
- public isPng(value: any): value is string {
183
- if (ValidateStringUtil.isBase64(value) === false) {
184
- return false
185
- }
186
-
187
- if (value.startsWith('data:')) {
188
- if (value.startsWith('data:image/png,') === false) {
189
- return false;
190
- }
191
-
192
- const valueParts = value.split(',');
193
- if (valueParts.length !== 2) {
194
- return false;
195
- }
196
-
197
- return valueParts[1].startsWith(this.PREFIX_PNG_DATA);
198
- }
199
-
200
- return value.startsWith(this.PREFIX_PNG_DATA);
201
- }
202
-
203
- public async tryConvertToPng(base64Value: any): Promise<string | false> {
204
- if (ValidateStringUtil.isBase64(base64Value) === false) {
205
- return false;
206
- }
207
-
208
- const base64Data = base64Value.startsWith('data:') ? base64Value.split(',')[1] : base64Value;
209
- if (this.isPng(base64Data)) {
210
- return base64Data;
211
- } else if (this.isJpeg(base64Data)) {
212
- const buffer = Buffer.from(base64Data, 'base64');
213
- try {
214
- const pngBuffer = await sharp(buffer)
215
- .ensureAlpha().png().toBuffer();
216
- return pngBuffer.toString('base64');
217
- } catch (e) {
218
- return false;
219
- }
220
- }
221
-
222
- return false;
223
- }
224
-
225
- public async resizeImage(base64Data: string, toSize: {w: number} | {h: number} | {w: number; h: number; func: 'max' | 'min'}| {rate: number}): Promise<string> {
226
- if (ValidateStringUtil.isBase64(base64Data) === false) {
227
- throw new Error("The specified data is not in base64 format");
228
- }
229
-
230
- const imageBuffer = Buffer.from(base64Data, 'base64');
231
- const metadata = await sharp(imageBuffer).metadata();
232
- const { width, height, format } = metadata;
233
- if (width === undefined || height === undefined) {
234
- throw new Error("Failed to retrieve image dimensions");
235
- }
236
-
237
- let rate = 1;
238
- if ('rate' in toSize) {
239
- rate = toSize.rate;
240
- } else if ('w' in toSize && 'h' in toSize && 'func' in toSize) {
241
- const wRate = toSize.w / width;
242
- const hRate = toSize.h / height;
243
- switch (toSize.func) {
244
- case 'max':
245
- rate = Math.max(wRate, hRate);
246
- break;
247
- case 'min':
248
- rate = Math.min(wRate, hRate);
249
- break;
250
- }
251
-
252
- } else if ('w' in toSize) {
253
- rate = toSize.w / width;
254
- } else if ('h' in toSize) {
255
- rate = toSize.h / height;
256
- }
257
-
258
- // 画像は1倍より大きくできないので
259
- if (rate >= 1 || rate <= 0) {
260
- return base64Data;
261
- }
262
-
263
- let resizedImage: Buffer;
264
-
265
- // フォーマットに応じて処理を分岐
266
- const targetWidth = Math.round(width * rate);
267
- const targetHeight = Math.round(height * rate);
268
- if (format === 'png') {
269
- resizedImage = await sharp(imageBuffer)
270
- .resize(targetWidth, targetHeight, {
271
- fit: 'inside',
272
- withoutEnlargement: true
273
- })
274
- .png({ quality: 90 })
275
- .toBuffer();
276
- } else {
277
- // JPEG、その他のフォーマット
278
- resizedImage = await sharp(imageBuffer)
279
- .resize(targetWidth, targetHeight, {
280
- fit: 'inside',
281
- withoutEnlargement: true
282
- })
283
- .jpeg({ quality: 90 })
284
- .toBuffer();
285
- }
286
-
287
- return resizedImage.toString('base64');
288
- }
289
-
290
- public async fetchImageAsBase64(imageUrl: string): Promise<string> {
291
- const res = await axios.get(imageUrl, {
292
- responseType: 'arraybuffer' // これを追加
293
- });
294
-
295
- // Content-Typeをチェック
296
- const contentType = res.headers['content-type'];
297
- if (!contentType?.startsWith('image/')) {
298
- throw new Error(`Invalid content type: ${contentType}. Expected image/*`);
299
- }
300
-
301
- // ArrayBufferをBufferに変換してBase64にエンコード
302
- const buffer = Buffer.from(res.data);
303
- return buffer.toString('base64');
304
- }
305
- }