@onlook/storybook-plugin 0.4.0-beta.5 → 0.4.0-beta.7

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/README.md CHANGED
@@ -44,7 +44,7 @@ Configures Vite HMR for E2B sandboxes (WSS protocol, port 443 routing).
44
44
 
45
45
  ### CORS
46
46
 
47
- Pre-configured for `https://app.onlook.ai`, `localhost:3000`, and `localhost:6006`.
47
+ Pre-configured for `https://app.onlook.com`, `localhost:3000`, and `localhost:6006`.
48
48
 
49
49
  ## Options
50
50
 
package/dist/cli/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
2
3
  import { command, string, boolean, run } from '@drizzle-team/brocli';
3
4
  import { spawn } from 'child_process';
4
5
  import fs, { readFileSync, existsSync } from 'fs';
@@ -6,6 +7,7 @@ import path, { resolve, join, dirname } from 'path';
6
7
  import crypto from 'crypto';
7
8
  import { chromium } from 'playwright';
8
9
 
10
+ globalThis.require = createRequire(import.meta.url);
9
11
  var CACHE_DIR = path.join(process.cwd(), ".storybook-cache");
10
12
  var SCREENSHOTS_DIR = path.join(CACHE_DIR, "screenshots");
11
13
  var MANIFEST_PATH = path.join(CACHE_DIR, "manifest.json");
@@ -190,6 +192,33 @@ async function generateScreenshot(storyId, theme, storybookUrl = "http://localho
190
192
  }
191
193
 
192
194
  // src/screenshot-service/screenshot-service.ts
195
+ var StoryTimeoutError = class extends Error {
196
+ constructor(storyId, timeoutMs) {
197
+ super(`Story ${storyId} timed out after ${timeoutMs / 1e3}s`);
198
+ this.storyId = storyId;
199
+ this.timeoutMs = timeoutMs;
200
+ this.name = "StoryTimeoutError";
201
+ }
202
+ };
203
+ async function captureBothThemes(storyId, storybookUrl, timeoutMs, storyTimeoutMs) {
204
+ let timer;
205
+ try {
206
+ return await Promise.race([
207
+ Promise.all([
208
+ generateScreenshot(storyId, "light", storybookUrl, timeoutMs),
209
+ generateScreenshot(storyId, "dark", storybookUrl, timeoutMs)
210
+ ]),
211
+ new Promise((_, reject) => {
212
+ timer = setTimeout(
213
+ () => reject(new StoryTimeoutError(storyId, storyTimeoutMs)),
214
+ storyTimeoutMs
215
+ );
216
+ })
217
+ ]);
218
+ } finally {
219
+ if (timer) clearTimeout(timer);
220
+ }
221
+ }
193
222
  async function generateAllScreenshots(stories, storybookUrl = "http://localhost:6006", concurrency = 10, offset = 0, total, skipExisting = false, timeoutMs = 3e4) {
194
223
  const displayTotal = total ?? offset + stories.length;
195
224
  console.log(
@@ -200,53 +229,74 @@ async function generateAllScreenshots(stories, storybookUrl = "http://localhost:
200
229
  for (let i = 0; i < stories.length; i += BATCH_SIZE) {
201
230
  batches.push(stories.slice(i, i + BATCH_SIZE));
202
231
  }
232
+ const storyTimeout = timeoutMs * 2 + 1e4;
203
233
  let completed = 0;
204
234
  for (const batch of batches) {
205
235
  await Promise.all(
206
236
  batch.map(async (story) => {
207
237
  if (skipExisting && screenshotExists(story.id, "light") && screenshotExists(story.id, "dark")) {
208
238
  completed++;
209
- const absoluteIndex = offset + completed;
210
- console.log(`[${absoluteIndex}/${displayTotal}] Skipped (exists) ${story.id}`);
239
+ const absoluteIndex2 = offset + completed;
240
+ console.log(`[${absoluteIndex2}/${displayTotal}] Skipped (exists) ${story.id}`);
211
241
  return;
212
242
  }
213
- const storyTimeout = timeoutMs * 2 + 1e4;
214
- let timer;
215
- try {
216
- const result = await Promise.race([
217
- Promise.all([
218
- generateScreenshot(story.id, "light", storybookUrl, timeoutMs),
219
- generateScreenshot(story.id, "dark", storybookUrl, timeoutMs)
220
- ]),
221
- new Promise((_, reject) => {
222
- timer = setTimeout(
223
- () => reject(
224
- new Error(
225
- `Story ${story.id} timed out after ${storyTimeout / 1e3}s`
226
- )
227
- ),
228
- storyTimeout
229
- );
230
- })
231
- ]);
232
- clearTimeout(timer);
233
- const [lightResult, darkResult] = result;
234
- if (lightResult && darkResult) {
235
- const fileHash = computeFileHash(story.importPath);
236
- updateManifest(story.id, story.importPath, fileHash, lightResult.boundingBox);
243
+ let lightResult = null;
244
+ let darkResult = null;
245
+ let lastError;
246
+ const startedAt = Date.now();
247
+ let attempts = 0;
248
+ const maxAttempts = 2;
249
+ while (attempts < maxAttempts) {
250
+ attempts++;
251
+ try {
252
+ [lightResult, darkResult] = await captureBothThemes(
253
+ story.id,
254
+ storybookUrl,
255
+ timeoutMs,
256
+ storyTimeout
257
+ );
258
+ lastError = void 0;
259
+ break;
260
+ } catch (error) {
261
+ lastError = error;
262
+ if (!(error instanceof StoryTimeoutError) || attempts >= maxAttempts) {
263
+ break;
264
+ }
265
+ console.warn(
266
+ `[screenshot] Retrying ${story.id} after timeout (attempt ${attempts + 1}/${maxAttempts})`
267
+ );
237
268
  }
238
- completed++;
239
- const absoluteIndex = offset + completed;
269
+ }
270
+ completed++;
271
+ const absoluteIndex = offset + completed;
272
+ const durationMs = Date.now() - startedAt;
273
+ if (lightResult && darkResult) {
274
+ const fileHash = computeFileHash(story.importPath);
275
+ updateManifest(story.id, story.importPath, fileHash, lightResult.boundingBox);
240
276
  console.log(
241
- `[${absoluteIndex}/${displayTotal}] Generated screenshots for ${story.id}`
277
+ `[${absoluteIndex}/${displayTotal}] Generated screenshots for ${story.id}`,
278
+ { storyId: story.id, attempts, durationMs, outcome: "ok" }
242
279
  );
243
- } catch (error) {
244
- completed++;
245
- const absoluteIndex = offset + completed;
280
+ } else if (lastError) {
246
281
  console.error(
247
282
  `[${absoluteIndex}/${displayTotal}] \u26A0\uFE0F Failed ${story.id}:`,
248
- error instanceof Error ? error.message : error
283
+ lastError instanceof Error ? lastError.message : lastError,
284
+ {
285
+ storyId: story.id,
286
+ attempts,
287
+ durationMs,
288
+ outcome: lastError instanceof StoryTimeoutError ? "timeout" : "error"
289
+ }
249
290
  );
291
+ } else {
292
+ console.warn(`[${absoluteIndex}/${displayTotal}] Partial result ${story.id}`, {
293
+ storyId: story.id,
294
+ attempts,
295
+ durationMs,
296
+ outcome: "partial",
297
+ hasLight: !!lightResult,
298
+ hasDark: !!darkResult
299
+ });
250
300
  }
251
301
  })
252
302
  );
package/dist/index.d.ts CHANGED
@@ -1,24 +1,18 @@
1
1
  import { PluginOption } from 'vite';
2
+ import { Indexer } from 'storybook/internal/types';
2
3
 
3
- /** Folder name for auto-generated stories (created next to each component) */
4
- declare const AUTO_STORIES_FOLDER = ".onlook-stories";
5
4
  type OnlookPluginOptions = {
6
5
  /** Storybook port (default: 6006) */
7
6
  port?: number;
8
7
  /** Additional allowed origins for CORS (merged with defaults) */
9
8
  allowedOrigins?: string[];
10
- /**
11
- * Auto-generate stories for all components.
12
- * Glob patterns for component file discovery.
13
- * Set to false to disable. (default: ['src\/\*\*\/*.tsx'])
14
- */
15
- autoStories?: string[] | false;
16
- /**
17
- * Glob patterns to exclude from auto-story generation.
18
- * (default: stories, tests, and node_modules)
19
- */
20
- autoStoriesIgnore?: string[];
9
+ hmr?: {
10
+ protocol?: 'ws' | 'wss';
11
+ clientPort?: number;
12
+ };
21
13
  };
22
14
  declare function storybookOnlookPlugin(options?: OnlookPluginOptions): PluginOption[];
23
15
 
24
- export { AUTO_STORIES_FOLDER, type OnlookPluginOptions, storybookOnlookPlugin };
16
+ declare const tolerantCsfIndexer: Indexer;
17
+
18
+ export { type OnlookPluginOptions, storybookOnlookPlugin, tolerantCsfIndexer };