create-forgeon 0.3.14 → 0.3.15

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.
@@ -240,14 +240,77 @@ function patchApiDockerfile(targetRoot) {
240
240
  content = ensureLineAfter(content, sourceAnchor, 'COPY packages/queue packages/queue');
241
241
 
242
242
  content = content.replace(/^RUN pnpm --filter @forgeon\/queue build\r?\n?/gm, '');
243
- const buildAnchor = content.includes('RUN pnpm --filter @forgeon/api prisma:generate')
244
- ? 'RUN pnpm --filter @forgeon/api prisma:generate'
245
- : 'RUN pnpm --filter @forgeon/api build';
243
+ const buildAnchors = [
244
+ 'RUN pnpm --filter @forgeon/scheduler build',
245
+ 'RUN pnpm --filter @forgeon/api prisma:generate',
246
+ 'RUN pnpm --filter @forgeon/api build',
247
+ ];
248
+ const buildAnchor = buildAnchors.find((line) => content.includes(line)) ?? 'RUN pnpm --filter @forgeon/api build';
246
249
  content = ensureLineBefore(content, buildAnchor, 'RUN pnpm --filter @forgeon/queue build');
247
250
 
248
251
  fs.writeFileSync(dockerfilePath, `${content.trimEnd()}\n`, 'utf8');
249
252
  }
250
253
 
254
+ function ensureApiDependsOnRedis(apiBlock) {
255
+ let lines = apiBlock.replace(/\n$/, '').split('\n');
256
+ const buildIndex = lines.findIndex((line) => line === ' build:');
257
+
258
+ // Heal a previously broken queue patch where depends_on was injected inside the build block.
259
+ if (buildIndex >= 0 && lines[buildIndex + 1] === ' depends_on:') {
260
+ let malformedBlockEnd = lines.length;
261
+ for (let index = buildIndex + 2; index < lines.length; index += 1) {
262
+ if (lines[index].startsWith(' ') && !lines[index].startsWith(' ')) {
263
+ malformedBlockEnd = index;
264
+ break;
265
+ }
266
+ }
267
+
268
+ const misplacedBuildLines = lines
269
+ .slice(buildIndex + 2, malformedBlockEnd)
270
+ .filter((line) => /^( context:| dockerfile:| args:| target:)/.test(line));
271
+
272
+ if (misplacedBuildLines.length > 0) {
273
+ lines = [
274
+ ...lines.slice(0, buildIndex + 1),
275
+ ...misplacedBuildLines,
276
+ ...lines.slice(malformedBlockEnd),
277
+ ];
278
+ }
279
+ }
280
+
281
+ const dependsOnIndex = lines.findIndex((line) => line === ' depends_on:');
282
+
283
+ if (dependsOnIndex < 0) {
284
+ const restartIndex = lines.findIndex((line) => line === ' restart: unless-stopped');
285
+ const environmentIndex = lines.findIndex((line) => line === ' environment:');
286
+ const insertAt = restartIndex >= 0 ? restartIndex + 1 : environmentIndex >= 0 ? environmentIndex : lines.length;
287
+ lines.splice(insertAt, 0, ' depends_on:', ' redis:', ' condition: service_healthy');
288
+ return `${lines.join('\n')}\n`;
289
+ }
290
+
291
+ let blockEnd = lines.length;
292
+ for (let index = dependsOnIndex + 1; index < lines.length; index += 1) {
293
+ if (lines[index].startsWith(' ') && !lines[index].startsWith(' ')) {
294
+ blockEnd = index;
295
+ break;
296
+ }
297
+ }
298
+
299
+ const dependsOnBlock = lines.slice(dependsOnIndex + 1, blockEnd);
300
+ const hasRedisMapping = dependsOnBlock.includes(' redis:');
301
+ const hasRedisList = dependsOnBlock.some((line) => line.trim() === '- redis');
302
+ if (hasRedisMapping || hasRedisList) {
303
+ return `${lines.join('\n')}\n`;
304
+ }
305
+
306
+ const isListStyle = dependsOnBlock.some((line) => line.trimStart().startsWith('- '));
307
+ const insertLines = isListStyle
308
+ ? [' - redis']
309
+ : [' redis:', ' condition: service_healthy'];
310
+
311
+ lines.splice(blockEnd, 0, ...insertLines);
312
+ return `${lines.join('\n')}\n`;
313
+ }
251
314
  function patchCompose(targetRoot) {
252
315
  const composePath = path.join(targetRoot, 'infra', 'docker', 'compose.yml');
253
316
  if (!fs.existsSync(composePath)) {
@@ -300,45 +363,14 @@ function patchCompose(targetRoot) {
300
363
  );
301
364
  }
302
365
 
303
- const apiBlockMatch = content.match(/^ api:\n[\s\S]*?(?=^ [a-zA-Z0-9_-]+:\n|^volumes:\n|$)/m);
366
+ const apiBlockMatch = content.match(/^ api:\n[\s\S]*?(?=^ [a-zA-Z0-9_-]+:\n|^volumes:\n|(?![\s\S]))/m);
304
367
  if (apiBlockMatch) {
305
- let apiBlock = apiBlockMatch[0];
306
- if (!/^\s{6}redis:\s*$/m.test(apiBlock) && !/^\s{6}-\s*redis\s*$/m.test(apiBlock)) {
307
- if (/^\s{4}depends_on:\s*$/m.test(apiBlock)) {
308
- if (/^\s{6}-\s+/m.test(apiBlock)) {
309
- apiBlock = apiBlock.replace(
310
- /^(\s{4}depends_on:\n(?:\s{6}-\s+.+\n)+)/m,
311
- `$1 - redis
312
- `,
313
- );
314
- } else {
315
- apiBlock = apiBlock.replace(
316
- /^(\s{4}depends_on:\n)/m,
317
- `$1 redis:
318
- condition: service_healthy
319
- `,
320
- );
321
- }
322
- } else {
323
- const withDependsOn = apiBlock.replace(
324
- /^(\s{4}environment:\n(?:\s{6}.+\n)+)/m,
325
- `$1 depends_on:
326
- redis:
327
- condition: service_healthy
328
- `,
329
- );
330
- apiBlock =
331
- withDependsOn === apiBlock
332
- ? `${apiBlock.trimEnd()}\n depends_on:\n redis:\n condition: service_healthy\n`
333
- : withDependsOn;
334
- }
335
- }
368
+ const apiBlock = ensureApiDependsOnRedis(apiBlockMatch[0]);
336
369
  content = content.replace(apiBlockMatch[0], apiBlock);
337
370
  }
338
371
 
339
372
  fs.writeFileSync(composePath, `${content.trimEnd()}\n`, 'utf8');
340
373
  }
341
-
342
374
  function patchReadme(targetRoot) {
343
375
  const readmePath = path.join(targetRoot, 'README.md');
344
376
  if (!fs.existsSync(readmePath)) {
@@ -409,4 +441,3 @@ export function applyQueueModule({ packageRoot, targetRoot }) {
409
441
  'QUEUE_DEFAULT_BACKOFF_MS=1000',
410
442
  ]);
411
443
  }
412
-