@pygmalionjs/pygmalion 0.5.16 → 0.5.18

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.
@@ -77,7 +77,7 @@ export type RoutePreviewArtifactResolution = {
77
77
  status: 'generating';
78
78
  } | {
79
79
  status: 'error';
80
- reason: 'unavailable' | 'rejected';
80
+ reason: 'unavailable' | 'rejected' | 'not-prepared';
81
81
  message: string;
82
82
  } | {
83
83
  status: 'exact';
@@ -87,6 +87,7 @@ export type RoutePreviewArtifactFrameRequestResult = {
87
87
  } | {
88
88
  status: 'unavailable';
89
89
  message?: string;
90
+ notPrepared?: boolean;
90
91
  } | {
91
92
  status: 'rejected';
92
93
  message: string;
@@ -207,6 +207,43 @@ export function pygmalionPreviewArtifactPlugin({
207
207
  return current;
208
208
  }
209
209
 
210
+ /**
211
+ * Answers a generation failure as what it is.
212
+ *
213
+ * A defective generator is a 500 the consumer must surface. A capture that
214
+ * could not run is a 503 it should wait out — the frame keeps whatever it has
215
+ * and says "not prepared yet" instead of painting a red failure over a screen
216
+ * whose only problem is that no runtime was asked for.
217
+ */
218
+ function sendGenerationFailure(response, error) {
219
+ if (error?.pygmalionBadGeneratorOutput) {
220
+ sendJson(response, 500, { ok: false, error: 'artifact_generation_failed' });
221
+ return;
222
+ }
223
+ sendJson(response, 503, {
224
+ ok: false,
225
+ error: 'artifact_generation_unavailable',
226
+ retryable: true,
227
+ details: [
228
+ error instanceof Error ? error.message.split('\n')[0] : String(error),
229
+ ],
230
+ });
231
+ }
232
+
233
+ /**
234
+ * A generator that ran and produced the wrong thing.
235
+ *
236
+ * Two very different failures reach the same catch: the capture could not run
237
+ * at all — the editor no longer prepares a checkout just because it started,
238
+ * so asking for a frame before anyone asked for the runtime is ordinary — and
239
+ * the capture ran but handed back something invalid or belonging to another
240
+ * revision. Only the second is a defect. Reporting both as one made the first
241
+ * shout, and quieting both would have hushed the second.
242
+ */
243
+ function badGeneratorOutput(message) {
244
+ return Object.assign(new Error(message), { pygmalionBadGeneratorOutput: true });
245
+ }
246
+
210
247
  async function withCaptureLease(sourceRevision, task) {
211
248
  // A capture reads the dev mirror for minutes. Hold a lease for that whole
212
249
  // window so a sync on another server cannot switch the checkout the frames
@@ -241,10 +278,10 @@ export function pygmalionPreviewArtifactPlugin({
241
278
  );
242
279
  const validation = validateRoutePreviewArtifactBundle(generated);
243
280
  if (!validation.valid) {
244
- throw new Error('Generated preview artifact is invalid.');
281
+ throw badGeneratorOutput('Generated preview artifact is invalid.');
245
282
  }
246
283
  if (!exactArtifact(generated, namespace, sourceRevision)) {
247
- throw new Error(
284
+ throw badGeneratorOutput(
248
285
  'Generated preview artifact identity does not match the request.',
249
286
  );
250
287
  }
@@ -426,11 +463,8 @@ export function pygmalionPreviewArtifactPlugin({
426
463
  sourceRevision,
427
464
  wanted,
428
465
  );
429
- } catch {
430
- sendJson(response, 500, {
431
- ok: false,
432
- error: 'artifact_generation_failed',
433
- });
466
+ } catch (error) {
467
+ sendGenerationFailure(response, error);
434
468
  return;
435
469
  }
436
470
  }
@@ -458,11 +492,8 @@ export function pygmalionPreviewArtifactPlugin({
458
492
  sourceRevision,
459
493
  captureBaseUrl,
460
494
  );
461
- } catch {
462
- sendJson(response, 500, {
463
- ok: false,
464
- error: 'artifact_generation_failed',
465
- });
495
+ } catch (error) {
496
+ sendGenerationFailure(response, error);
466
497
  return;
467
498
  }
468
499
  }
@@ -498,11 +529,8 @@ export function pygmalionPreviewArtifactPlugin({
498
529
  sourceRevision,
499
530
  captureBaseUrl,
500
531
  );
501
- } catch {
502
- sendJson(response, 500, {
503
- ok: false,
504
- error: 'artifact_generation_failed',
505
- });
532
+ } catch (error) {
533
+ sendGenerationFailure(response, error);
506
534
  return;
507
535
  }
508
536
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pygmalionjs/pygmalion",
3
- "version": "0.5.16",
3
+ "version": "0.5.18",
4
4
  "description": "Code-backed DOM design sandbox and visual QA editor",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {