create-forgeon 0.3.8 → 0.3.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-forgeon",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "description": "Forgeon project generator CLI",
5
5
  "license": "MIT",
6
6
  "author": "Forgeon",
@@ -440,6 +440,7 @@ function assertFilesImageWiring(projectRoot) {
440
440
  const appModule = fs.readFileSync(path.join(projectRoot, 'apps', 'api', 'src', 'app.module.ts'), 'utf8');
441
441
  assert.match(appModule, /filesImageConfig/);
442
442
  assert.match(appModule, /filesImageEnvSchema/);
443
+ assert.match(appModule, /ForgeonFilesImageModule/);
443
444
 
444
445
  const apiPackage = fs.readFileSync(path.join(projectRoot, 'apps', 'api', 'package.json'), 'utf8');
445
446
  assert.match(apiPackage, /@forgeon\/files-image/);
@@ -528,6 +529,10 @@ function assertFilesImageWiring(projectRoot) {
528
529
  assert.match(filesImagePackage, /"sharp":/);
529
530
  assert.match(filesImagePackage, /"file-type":/);
530
531
 
532
+ const rootPackage = fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8');
533
+ assert.match(rootPackage, /"onlyBuiltDependencies"/);
534
+ assert.match(rootPackage, /"sharp"/);
535
+
531
536
  const readme = fs.readFileSync(path.join(projectRoot, 'README.md'), 'utf8');
532
537
  assert.match(readme, /## Files Image Module/);
533
538
  assert.match(readme, /metadata is stripped before storage/i);
@@ -53,6 +53,29 @@ function patchFilesPackage(targetRoot) {
53
53
  writeJson(packagePath, packageJson);
54
54
  }
55
55
 
56
+ function patchRootPackage(targetRoot) {
57
+ const packagePath = path.join(targetRoot, 'package.json');
58
+ if (!fs.existsSync(packagePath)) {
59
+ return;
60
+ }
61
+
62
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
63
+ if (!packageJson.pnpm || typeof packageJson.pnpm !== 'object' || Array.isArray(packageJson.pnpm)) {
64
+ packageJson.pnpm = {};
65
+ }
66
+
67
+ const onlyBuiltDependencies = Array.isArray(packageJson.pnpm.onlyBuiltDependencies)
68
+ ? packageJson.pnpm.onlyBuiltDependencies
69
+ : [];
70
+
71
+ if (!onlyBuiltDependencies.includes('sharp')) {
72
+ onlyBuiltDependencies.push('sharp');
73
+ }
74
+
75
+ packageJson.pnpm.onlyBuiltDependencies = onlyBuiltDependencies;
76
+ writeJson(packagePath, packageJson);
77
+ }
78
+
56
79
  function patchFilesTypes(targetRoot) {
57
80
  const filePath = path.join(targetRoot, 'packages', 'files', 'src', 'files.types.ts');
58
81
  if (!fs.existsSync(filePath)) {
@@ -84,11 +107,31 @@ function patchAppModule(targetRoot) {
84
107
  let content = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
85
108
  content = ensureImportLine(
86
109
  content,
87
- "import { filesImageConfig, filesImageEnvSchema } from '@forgeon/files-image';",
110
+ "import { filesImageConfig, filesImageEnvSchema, ForgeonFilesImageModule } from '@forgeon/files-image';",
88
111
  );
89
112
  content = ensureLoadItem(content, 'filesImageConfig');
90
113
  content = ensureValidatorSchema(content, 'filesImageEnvSchema');
91
114
 
115
+ if (!content.includes(' ForgeonFilesImageModule,')) {
116
+ if (content.includes(' ForgeonI18nModule.register({')) {
117
+ content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesImageModule,');
118
+ } else if (content.includes(' ForgeonAuthModule.register({')) {
119
+ content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonFilesImageModule,');
120
+ } else if (content.includes(' ForgeonAuthModule.register(),')) {
121
+ content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonFilesImageModule,');
122
+ } else if (content.includes(' ForgeonFilesModule,')) {
123
+ content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesImageModule,');
124
+ } else if (content.includes(' DbPrismaModule,')) {
125
+ content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesImageModule,');
126
+ } else if (content.includes(' ForgeonLoggerModule,')) {
127
+ content = ensureLineAfter(content, ' ForgeonLoggerModule,', ' ForgeonFilesImageModule,');
128
+ } else if (content.includes(' ForgeonSwaggerModule,')) {
129
+ content = ensureLineAfter(content, ' ForgeonSwaggerModule,', ' ForgeonFilesImageModule,');
130
+ } else {
131
+ content = ensureLineAfter(content, ' CoreErrorsModule,', ' ForgeonFilesImageModule,');
132
+ }
133
+ }
134
+
92
135
  fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
93
136
  }
94
137
 
@@ -506,6 +549,7 @@ export function applyFilesImageModule({ packageRoot, targetRoot }) {
506
549
  copyFromPreset(packageRoot, targetRoot, path.join('packages', 'files-image'));
507
550
  patchApiPackage(targetRoot);
508
551
  patchFilesPackage(targetRoot);
552
+ patchRootPackage(targetRoot);
509
553
  patchFilesTypes(targetRoot);
510
554
  patchAppModule(targetRoot);
511
555
  patchFilesModule(targetRoot);
@@ -146,50 +146,85 @@ export class FilesImageService {
146
146
  return this.configService.enabled;
147
147
  }
148
148
 
149
- async getProbeStatus(): Promise<{
150
- status: 'ok';
151
- feature: 'files-image';
152
- stripMetadata: boolean;
153
- maxWidth: number;
154
- maxHeight: number;
155
- maxPixels: number;
156
- maxFrames: number;
157
- inputBytes: number;
158
- outputBytes: number;
159
- outputMimeType: string;
160
- transformed: boolean;
161
- }> {
162
- const sample = await sharp({
163
- create: {
164
- width: 4,
165
- height: 4,
166
- channels: 3,
167
- background: { r: 120, g: 80, b: 40 },
168
- },
169
- })
170
- .jpeg({ quality: 90 })
171
- .withMetadata()
172
- .toBuffer();
173
-
174
- const result = await this.sanitizeForStorage({
175
- buffer: sample,
176
- declaredMimeType: 'image/jpeg',
177
- originalName: 'probe.jpg',
178
- });
149
+ async getProbeStatus(): Promise<
150
+ | {
151
+ status: 'ok';
152
+ feature: 'files-image';
153
+ stripMetadata: boolean;
154
+ maxWidth: number;
155
+ maxHeight: number;
156
+ maxPixels: number;
157
+ maxFrames: number;
158
+ inputBytes: number;
159
+ outputBytes: number;
160
+ outputMimeType: string;
161
+ transformed: boolean;
162
+ }
163
+ | {
164
+ status: 'error';
165
+ feature: 'files-image';
166
+ stripMetadata: boolean;
167
+ maxWidth: number;
168
+ maxHeight: number;
169
+ maxPixels: number;
170
+ maxFrames: number;
171
+ errorCode: string;
172
+ errorMessage: string;
173
+ }
174
+ > {
175
+ try {
176
+ const sample = await sharp({
177
+ create: {
178
+ width: 4,
179
+ height: 4,
180
+ channels: 3,
181
+ background: { r: 120, g: 80, b: 40 },
182
+ },
183
+ })
184
+ .jpeg({ quality: 90 })
185
+ .withMetadata()
186
+ .toBuffer();
187
+
188
+ const result = await this.sanitizeForStorage({
189
+ buffer: sample,
190
+ declaredMimeType: 'image/jpeg',
191
+ originalName: 'probe.jpg',
192
+ });
179
193
 
180
- return {
181
- status: 'ok',
182
- feature: 'files-image',
183
- stripMetadata: this.configService.stripMetadata,
184
- maxWidth: this.configService.maxWidth,
185
- maxHeight: this.configService.maxHeight,
186
- maxPixels: this.configService.maxPixels,
187
- maxFrames: this.configService.maxFrames,
188
- inputBytes: sample.byteLength,
189
- outputBytes: result.buffer.byteLength,
190
- outputMimeType: result.mimeType,
191
- transformed: result.transformed,
192
- };
194
+ return {
195
+ status: 'ok',
196
+ feature: 'files-image',
197
+ stripMetadata: this.configService.stripMetadata,
198
+ maxWidth: this.configService.maxWidth,
199
+ maxHeight: this.configService.maxHeight,
200
+ maxPixels: this.configService.maxPixels,
201
+ maxFrames: this.configService.maxFrames,
202
+ inputBytes: sample.byteLength,
203
+ outputBytes: result.buffer.byteLength,
204
+ outputMimeType: result.mimeType,
205
+ transformed: result.transformed,
206
+ };
207
+ } catch (error) {
208
+ const errorMessage = error instanceof Error ? error.message : 'Unknown files-image probe error';
209
+ this.logger.error(
210
+ JSON.stringify({
211
+ event: 'files.image.probe_failed',
212
+ errorMessage,
213
+ }),
214
+ );
215
+
216
+ return {
217
+ status: 'error',
218
+ feature: 'files-image',
219
+ stripMetadata: this.configService.stripMetadata,
220
+ maxWidth: this.configService.maxWidth,
221
+ maxHeight: this.configService.maxHeight,
222
+ maxPixels: this.configService.maxPixels,
223
+ maxFrames: this.configService.maxFrames,
224
+ errorCode: 'FILES_IMAGE_PROBE_FAILED',
225
+ errorMessage,
226
+ };
227
+ }
193
228
  }
194
229
 
195
230
  private async detectFileType(buffer: Buffer): Promise<{ mime: string; ext: string } | null> {