vite-plugin-opal 0.3.1 → 0.3.3

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/dist/index.d.ts CHANGED
@@ -135,6 +135,75 @@ interface OpalPluginOptions {
135
135
  * ```
136
136
  */
137
137
  includeConcerns?: boolean;
138
+ /**
139
+ * Enable disk-based caching for compiled files.
140
+ * Persists cache across dev server restarts for faster rebuilds.
141
+ * Cache is stored in node_modules/.cache/opal-vite/
142
+ *
143
+ * @default true
144
+ * @example
145
+ * ```ts
146
+ * {
147
+ * diskCache: true // Enable persistent caching
148
+ * }
149
+ * ```
150
+ */
151
+ diskCache?: boolean;
152
+ /**
153
+ * Custom directory for disk cache.
154
+ * If not specified, uses node_modules/.cache/opal-vite/
155
+ *
156
+ * @default undefined (auto-detect)
157
+ * @example
158
+ * ```ts
159
+ * {
160
+ * cacheDir: '.cache/opal'
161
+ * }
162
+ * ```
163
+ */
164
+ cacheDir?: string;
165
+ /**
166
+ * Modules to stub (replace with empty implementations).
167
+ * Useful for excluding server-side only gems or large unused libraries.
168
+ * Reduces bundle size by replacing modules with empty exports.
169
+ *
170
+ * @default []
171
+ * @example
172
+ * ```ts
173
+ * {
174
+ * stubs: ['active_support', 'sprockets', 'listen']
175
+ * }
176
+ * ```
177
+ */
178
+ stubs?: string[];
179
+ /**
180
+ * Maximum number of concurrent Ruby processes for compilation.
181
+ * Higher values can speed up initial builds with many files.
182
+ * Set to 1 to disable parallel compilation.
183
+ *
184
+ * @default 4
185
+ * @example
186
+ * ```ts
187
+ * {
188
+ * parallelCompilation: 8 // Allow 8 concurrent compilations
189
+ * }
190
+ * ```
191
+ */
192
+ parallelCompilation?: number;
193
+ /**
194
+ * Enable compilation metrics logging.
195
+ * Logs timing information for each compilation step.
196
+ * Useful for identifying performance bottlenecks.
197
+ *
198
+ * @default false
199
+ * @example
200
+ * ```ts
201
+ * {
202
+ * metrics: true // Enable performance metrics
203
+ * }
204
+ * ```
205
+ */
206
+ metrics?: boolean;
138
207
  }
139
208
 
140
209
  /**
package/dist/index.js CHANGED
@@ -1,14 +1,98 @@
1
1
  import { spawn } from 'child_process';
2
2
  import * as fs from 'fs/promises';
3
- import { accessSync } from 'fs';
4
- import * as path2 from 'path';
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, accessSync } from 'fs';
4
+ import * as path from 'path';
5
+ import * as crypto from 'crypto';
5
6
  import * as chokidar from 'chokidar';
6
7
 
7
- // src/compiler.ts
8
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
+ }) : x)(function(x) {
11
+ if (typeof require !== "undefined") return require.apply(this, arguments);
12
+ throw Error('Dynamic require of "' + x + '" is not supported');
13
+ });
14
+ function parseRubyError(stderr, filePath) {
15
+ const lines = stderr.trim().split("\n");
16
+ const error = {
17
+ message: stderr.trim(),
18
+ file: filePath,
19
+ rawOutput: stderr
20
+ };
21
+ for (const line of lines) {
22
+ const lineMatch = line.match(/^(.+?):(\d+)(?::(\d+))?(?::in `[^']+')?\s*[:\-]?\s*(.*)/);
23
+ if (lineMatch) {
24
+ const [, matchedFile, lineNum, colNum, msg] = lineMatch;
25
+ if (matchedFile.endsWith(".rb") || matchedFile.includes(filePath)) {
26
+ error.file = matchedFile;
27
+ error.line = parseInt(lineNum, 10);
28
+ if (colNum) {
29
+ error.column = parseInt(colNum, 10);
30
+ }
31
+ error.message = msg || line;
32
+ break;
33
+ }
34
+ }
35
+ }
36
+ const typeMatch = stderr.match(/(\w+Error|\w+Exception):\s*(.+)/m);
37
+ if (typeMatch) {
38
+ error.errorType = typeMatch[1];
39
+ if (!error.message || error.message === stderr.trim()) {
40
+ error.message = typeMatch[2].trim();
41
+ }
42
+ }
43
+ if (stderr.includes("SyntaxError")) {
44
+ error.errorType = "SyntaxError";
45
+ const syntaxMatch = stderr.match(/SyntaxError:\s*(.+?)(?:\n|$)/);
46
+ if (syntaxMatch) {
47
+ error.message = syntaxMatch[1];
48
+ }
49
+ } else if (stderr.includes("NameError")) {
50
+ error.errorType = "NameError";
51
+ const nameMatch = stderr.match(/NameError:\s*(.+?)(?:\n|$)/);
52
+ if (nameMatch) {
53
+ error.message = nameMatch[1];
54
+ }
55
+ } else if (stderr.includes("LoadError")) {
56
+ error.errorType = "LoadError";
57
+ const loadMatch = stderr.match(/LoadError:\s*(.+?)(?:\n|$)/);
58
+ if (loadMatch) {
59
+ error.message = loadMatch[1];
60
+ }
61
+ const requireMatch = stderr.match(/cannot load such file\s*--\s*(.+)/);
62
+ if (requireMatch) {
63
+ error.hint = `Check that '${requireMatch[1]}' exists and is in your load paths`;
64
+ }
65
+ }
66
+ return error;
67
+ }
68
+ function formatCompilationError(error) {
69
+ const parts = [];
70
+ const errorType = error.errorType || "CompilationError";
71
+ parts.push(`\x1B[31m\u2716 Opal ${errorType}\x1B[0m`);
72
+ if (error.file) {
73
+ let location = ` \x1B[36m\u2192 ${error.file}\x1B[0m`;
74
+ if (error.line) {
75
+ location += `\x1B[33m:${error.line}\x1B[0m`;
76
+ if (error.column) {
77
+ location += `\x1B[33m:${error.column}\x1B[0m`;
78
+ }
79
+ }
80
+ parts.push(location);
81
+ }
82
+ parts.push(` \x1B[37m${error.message}\x1B[0m`);
83
+ if (error.hint) {
84
+ parts.push(` \x1B[33m\u{1F4A1} ${error.hint}\x1B[0m`);
85
+ }
86
+ return parts.join("\n");
87
+ }
88
+ var CACHE_VERSION = "1.0.0";
8
89
  var OpalCompiler = class {
9
90
  constructor(options = {}) {
10
91
  this.cache = /* @__PURE__ */ new Map();
11
92
  this.runtimeCache = null;
93
+ this.metrics = [];
94
+ this.compilationQueue = Promise.resolve();
95
+ this.activeCompilations = 0;
12
96
  this.options = {
13
97
  gemPath: options.gemPath || "opal-vite",
14
98
  sourceMap: options.sourceMap !== false,
@@ -17,18 +101,99 @@ var OpalCompiler = class {
17
101
  freezing: options.freezing !== false,
18
102
  debug: options.debug || false,
19
103
  useBundler: options.useBundler !== void 0 ? options.useBundler : this.detectGemfile(),
20
- includeConcerns: options.includeConcerns !== false
104
+ includeConcerns: options.includeConcerns !== false,
105
+ diskCache: options.diskCache !== false,
106
+ cacheDir: options.cacheDir || "",
107
+ stubs: options.stubs || [],
108
+ parallelCompilation: options.parallelCompilation || 4,
109
+ metrics: options.metrics || false
21
110
  };
22
111
  this.useBundler = this.options.useBundler;
112
+ this.cacheDir = this.resolveCacheDir();
113
+ if (this.options.diskCache) {
114
+ this.ensureCacheDir();
115
+ }
23
116
  if (this.options.debug) {
24
117
  console.log(`[vite-plugin-opal] Using bundler: ${this.useBundler}`);
25
118
  console.log(`[vite-plugin-opal] Working directory: ${process.cwd()}`);
26
119
  console.log(`[vite-plugin-opal] Include concerns: ${this.options.includeConcerns}`);
120
+ console.log(`[vite-plugin-opal] Disk cache: ${this.options.diskCache ? "enabled" : "disabled"}`);
121
+ if (this.options.diskCache) {
122
+ console.log(`[vite-plugin-opal] Cache directory: ${this.cacheDir}`);
123
+ }
124
+ if (this.options.stubs.length > 0) {
125
+ console.log(`[vite-plugin-opal] Stubs: ${this.options.stubs.join(", ")}`);
126
+ }
127
+ console.log(`[vite-plugin-opal] Parallel compilation: ${this.options.parallelCompilation}`);
128
+ }
129
+ }
130
+ resolveCacheDir() {
131
+ if (this.options.cacheDir) {
132
+ return path.resolve(process.cwd(), this.options.cacheDir);
133
+ }
134
+ return path.resolve(process.cwd(), "node_modules", ".cache", "opal-vite");
135
+ }
136
+ ensureCacheDir() {
137
+ try {
138
+ if (!existsSync(this.cacheDir)) {
139
+ mkdirSync(this.cacheDir, { recursive: true });
140
+ this.log(`Created cache directory: ${this.cacheDir}`);
141
+ }
142
+ } catch (e) {
143
+ this.log(`Warning: Could not create cache directory: ${e}`);
144
+ }
145
+ }
146
+ getCacheKey(filePath) {
147
+ const normalized = path.resolve(filePath);
148
+ return crypto.createHash("md5").update(normalized).digest("hex");
149
+ }
150
+ getContentHash(content) {
151
+ return crypto.createHash("md5").update(content).digest("hex");
152
+ }
153
+ getDiskCachePath(filePath) {
154
+ return path.join(this.cacheDir, `${this.getCacheKey(filePath)}.json`);
155
+ }
156
+ async loadFromDiskCache(filePath, contentHash) {
157
+ if (!this.options.diskCache) return null;
158
+ const cachePath = this.getDiskCachePath(filePath);
159
+ try {
160
+ if (!existsSync(cachePath)) return null;
161
+ const cacheContent = readFileSync(cachePath, "utf-8");
162
+ const entry = JSON.parse(cacheContent);
163
+ if (entry.version !== CACHE_VERSION) {
164
+ this.log(`Disk cache version mismatch for ${filePath}`);
165
+ return null;
166
+ }
167
+ if (entry.contentHash !== contentHash) {
168
+ this.log(`Disk cache content hash mismatch for ${filePath}`);
169
+ return null;
170
+ }
171
+ this.log(`Disk cache hit: ${filePath}`);
172
+ return entry.result;
173
+ } catch (e) {
174
+ this.log(`Disk cache read error for ${filePath}: ${e}`);
175
+ return null;
176
+ }
177
+ }
178
+ saveToDiskCache(filePath, contentHash, mtime, result) {
179
+ if (!this.options.diskCache) return;
180
+ const cachePath = this.getDiskCachePath(filePath);
181
+ try {
182
+ const entry = {
183
+ version: CACHE_VERSION,
184
+ contentHash,
185
+ mtime,
186
+ result
187
+ };
188
+ writeFileSync(cachePath, JSON.stringify(entry), "utf-8");
189
+ this.log(`Disk cache saved: ${filePath}`);
190
+ } catch (e) {
191
+ this.log(`Disk cache write error for ${filePath}: ${e}`);
27
192
  }
28
193
  }
29
194
  detectGemfile() {
30
195
  try {
31
- const gemfilePath = path2.join(process.cwd(), "Gemfile");
196
+ const gemfilePath = path.join(process.cwd(), "Gemfile");
32
197
  accessSync(gemfilePath);
33
198
  return true;
34
199
  } catch {
@@ -36,34 +201,159 @@ var OpalCompiler = class {
36
201
  }
37
202
  }
38
203
  async compile(filePath) {
204
+ const startTime = this.options.metrics ? performance.now() : 0;
205
+ const stubResult = this.checkStub(filePath);
206
+ if (stubResult) {
207
+ this.recordMetrics(filePath, startTime, true, "memory");
208
+ return stubResult;
209
+ }
210
+ let fileContent;
211
+ let stat3;
212
+ try {
213
+ fileContent = await fs.readFile(filePath, "utf-8");
214
+ stat3 = await fs.stat(filePath);
215
+ } catch (e) {
216
+ throw new Error(`Failed to read file: ${filePath}`);
217
+ }
218
+ const contentHash = this.getContentHash(fileContent);
39
219
  const cached = this.cache.get(filePath);
40
220
  if (cached) {
41
- try {
42
- const stat3 = await fs.stat(filePath);
43
- if (stat3.mtimeMs <= cached.mtime) {
44
- this.log(`Cache hit: ${filePath}`);
45
- return {
46
- code: cached.code,
47
- map: cached.map,
48
- dependencies: cached.dependencies
49
- };
50
- }
51
- } catch (e) {
52
- this.cache.delete(filePath);
221
+ if (stat3.mtimeMs <= cached.mtime) {
222
+ this.log(`Memory cache hit: ${filePath}`);
223
+ this.recordMetrics(filePath, startTime, true, "memory");
224
+ return {
225
+ code: cached.code,
226
+ map: cached.map,
227
+ dependencies: cached.dependencies
228
+ };
53
229
  }
230
+ this.cache.delete(filePath);
54
231
  }
55
- this.log(`Compiling: ${filePath}`);
56
- const result = await this.compileViaRuby(filePath);
57
- try {
58
- const stat3 = await fs.stat(filePath);
232
+ const diskCached = await this.loadFromDiskCache(filePath, contentHash);
233
+ if (diskCached) {
59
234
  this.cache.set(filePath, {
60
- ...result,
235
+ ...diskCached,
61
236
  mtime: stat3.mtimeMs
62
237
  });
63
- } catch (e) {
238
+ this.recordMetrics(filePath, startTime, true, "disk");
239
+ return diskCached;
64
240
  }
241
+ this.log(`Compiling: ${filePath}`);
242
+ const result = await this.compileWithConcurrencyControl(filePath);
243
+ this.cache.set(filePath, {
244
+ ...result,
245
+ mtime: stat3.mtimeMs
246
+ });
247
+ this.saveToDiskCache(filePath, contentHash, stat3.mtimeMs, result);
248
+ this.recordMetrics(filePath, startTime, false, "compile");
65
249
  return result;
66
250
  }
251
+ /**
252
+ * Compile multiple files in parallel with concurrency control
253
+ */
254
+ async compileMany(filePaths) {
255
+ const results = /* @__PURE__ */ new Map();
256
+ const batchSize = this.options.parallelCompilation;
257
+ for (let i = 0; i < filePaths.length; i += batchSize) {
258
+ const batch = filePaths.slice(i, i + batchSize);
259
+ const batchResults = await Promise.all(
260
+ batch.map(async (filePath) => {
261
+ try {
262
+ const result = await this.compile(filePath);
263
+ return { filePath, result, error: null };
264
+ } catch (e) {
265
+ return { filePath, result: null, error: e };
266
+ }
267
+ })
268
+ );
269
+ for (const { filePath, result, error } of batchResults) {
270
+ if (result) {
271
+ results.set(filePath, result);
272
+ } else {
273
+ this.log(`Compilation failed for ${filePath}: ${error}`);
274
+ }
275
+ }
276
+ }
277
+ return results;
278
+ }
279
+ async compileWithConcurrencyControl(filePath) {
280
+ while (this.activeCompilations >= this.options.parallelCompilation) {
281
+ await new Promise((resolve4) => setTimeout(resolve4, 10));
282
+ }
283
+ this.activeCompilations++;
284
+ try {
285
+ return await this.compileViaRuby(filePath);
286
+ } finally {
287
+ this.activeCompilations--;
288
+ }
289
+ }
290
+ checkStub(filePath) {
291
+ if (this.options.stubs.length === 0) return null;
292
+ const fileName = path.basename(filePath, ".rb");
293
+ const isStubbed = this.options.stubs.some((stub) => {
294
+ if (stub === fileName) return true;
295
+ if (filePath.includes(`/${stub}/`) || filePath.includes(`/${stub}.rb`)) return true;
296
+ return false;
297
+ });
298
+ if (isStubbed) {
299
+ this.log(`Stubbed module: ${filePath}`);
300
+ return {
301
+ code: '// Stubbed module\nOpal.loaded(["' + fileName + '"]);\n',
302
+ map: void 0,
303
+ dependencies: []
304
+ };
305
+ }
306
+ return null;
307
+ }
308
+ recordMetrics(filePath, startTime, cacheHit, source) {
309
+ if (!this.options.metrics) return;
310
+ const duration = performance.now() - startTime;
311
+ this.metrics.push({
312
+ file: path.basename(filePath),
313
+ duration,
314
+ cacheHit,
315
+ source
316
+ });
317
+ }
318
+ /**
319
+ * Get compilation metrics summary
320
+ */
321
+ getMetricsSummary() {
322
+ const total = this.metrics.length;
323
+ const cached = this.metrics.filter((m) => m.cacheHit).length;
324
+ const compiled = total - cached;
325
+ const avgDuration = total > 0 ? this.metrics.reduce((sum, m) => sum + m.duration, 0) / total : 0;
326
+ return {
327
+ total,
328
+ cached,
329
+ compiled,
330
+ avgDuration: Math.round(avgDuration * 100) / 100,
331
+ details: [...this.metrics]
332
+ };
333
+ }
334
+ /**
335
+ * Print metrics summary to console
336
+ */
337
+ printMetricsSummary() {
338
+ const summary = this.getMetricsSummary();
339
+ console.log("\n[vite-plugin-opal] Compilation Metrics:");
340
+ console.log(` Total files: ${summary.total}`);
341
+ console.log(` Cache hits: ${summary.cached} (${Math.round(summary.cached / summary.total * 100) || 0}%)`);
342
+ console.log(` Compiled: ${summary.compiled}`);
343
+ console.log(` Avg duration: ${summary.avgDuration}ms`);
344
+ if (this.options.debug && summary.details.length > 0) {
345
+ console.log("\n Details:");
346
+ for (const m of summary.details) {
347
+ console.log(` ${m.file}: ${Math.round(m.duration)}ms (${m.source})`);
348
+ }
349
+ }
350
+ }
351
+ /**
352
+ * Clear metrics
353
+ */
354
+ clearMetrics() {
355
+ this.metrics = [];
356
+ }
67
357
  async getOpalRuntime() {
68
358
  if (this.runtimeCache) {
69
359
  return this.runtimeCache;
@@ -73,15 +363,69 @@ var OpalCompiler = class {
73
363
  this.runtimeCache = runtime;
74
364
  return runtime;
75
365
  }
76
- clearCache(filePath) {
366
+ clearCache(filePath, clearDisk = false) {
77
367
  if (filePath) {
78
368
  this.cache.delete(filePath);
369
+ if (clearDisk && this.options.diskCache) {
370
+ try {
371
+ const cachePath = this.getDiskCachePath(filePath);
372
+ if (existsSync(cachePath)) {
373
+ const fsSync = __require("fs");
374
+ fsSync.unlinkSync(cachePath);
375
+ }
376
+ } catch (e) {
377
+ this.log(`Failed to clear disk cache for ${filePath}: ${e}`);
378
+ }
379
+ }
79
380
  this.log(`Cache cleared: ${filePath}`);
80
381
  } else {
81
382
  this.cache.clear();
383
+ if (clearDisk && this.options.diskCache) {
384
+ this.clearDiskCache();
385
+ }
82
386
  this.log("Cache cleared (all)");
83
387
  }
84
388
  }
389
+ /**
390
+ * Clear all disk cache files
391
+ */
392
+ clearDiskCache() {
393
+ if (!this.options.diskCache) return;
394
+ try {
395
+ const fsSync = __require("fs");
396
+ if (existsSync(this.cacheDir)) {
397
+ const files = fsSync.readdirSync(this.cacheDir);
398
+ for (const file of files) {
399
+ if (file.endsWith(".json")) {
400
+ fsSync.unlinkSync(path.join(this.cacheDir, file));
401
+ }
402
+ }
403
+ this.log(`Cleared ${files.length} disk cache files`);
404
+ }
405
+ } catch (e) {
406
+ this.log(`Failed to clear disk cache: ${e}`);
407
+ }
408
+ }
409
+ /**
410
+ * Get disk cache statistics
411
+ */
412
+ getDiskCacheStats() {
413
+ if (!this.options.diskCache || !existsSync(this.cacheDir)) {
414
+ return { files: 0, size: 0 };
415
+ }
416
+ try {
417
+ const fsSync = __require("fs");
418
+ const files = fsSync.readdirSync(this.cacheDir).filter((f) => f.endsWith(".json"));
419
+ let totalSize = 0;
420
+ for (const file of files) {
421
+ const stat3 = fsSync.statSync(path.join(this.cacheDir, file));
422
+ totalSize += stat3.size;
423
+ }
424
+ return { files: files.length, size: totalSize };
425
+ } catch (e) {
426
+ return { files: 0, size: 0 };
427
+ }
428
+ }
85
429
  async compileViaRuby(filePath) {
86
430
  return new Promise((resolve4, reject) => {
87
431
  let command;
@@ -98,14 +442,13 @@ var OpalCompiler = class {
98
442
  filePath
99
443
  ];
100
444
  } else {
445
+ const gemLibPath = this.resolveGemLibPath();
101
446
  command = "ruby";
102
447
  args = [
103
448
  "-I",
104
- this.resolveGemLibPath(),
105
- "-r",
106
- "opal-vite",
449
+ gemLibPath,
107
450
  "-e",
108
- this.getCompilerScript(),
451
+ `$LOAD_PATH.unshift('${gemLibPath}'); require 'opal-vite'; ${this.getCompilerScript()}`,
109
452
  filePath
110
453
  ];
111
454
  }
@@ -123,21 +466,37 @@ var OpalCompiler = class {
123
466
  });
124
467
  ruby.on("close", (code) => {
125
468
  if (code !== 0) {
126
- reject(new Error(`Opal compilation failed:
127
- ${stderr}`));
469
+ const parsedError = parseRubyError(stderr, filePath);
470
+ const formattedMessage = formatCompilationError(parsedError);
471
+ console.error(formattedMessage);
472
+ const error = new Error(parsedError.message);
473
+ error.file = parsedError.file;
474
+ error.line = parsedError.line;
475
+ error.column = parsedError.column;
476
+ error.errorType = parsedError.errorType;
477
+ error.hint = parsedError.hint;
478
+ error.rawOutput = parsedError.rawOutput;
479
+ reject(error);
128
480
  return;
129
481
  }
130
482
  try {
131
483
  const result = JSON.parse(stdout);
132
484
  resolve4(result);
133
485
  } catch (e) {
134
- reject(new Error(`Failed to parse compiler output:
135
- ${stdout}
136
-
137
- Error: ${e}`));
486
+ const parseError = new Error(`Failed to parse compiler output: ${e}`);
487
+ console.error("\x1B[31m\u2716 Opal Compiler Output Parse Error\x1B[0m");
488
+ console.error(` \x1B[36m\u2192 ${filePath}\x1B[0m`);
489
+ console.error(` \x1B[37mUnexpected output from Ruby compiler\x1B[0m`);
490
+ if (this.options.debug) {
491
+ console.error(` \x1B[90mRaw output: ${stdout.substring(0, 500)}...\x1B[0m`);
492
+ }
493
+ reject(parseError);
138
494
  }
139
495
  });
140
496
  ruby.on("error", (err) => {
497
+ console.error("\x1B[31m\u2716 Ruby Process Error\x1B[0m");
498
+ console.error(` \x1B[37m${err.message}\x1B[0m`);
499
+ console.error(` \x1B[33m\u{1F4A1} Make sure Ruby and Opal are installed correctly\x1B[0m`);
141
500
  reject(new Error(`Failed to spawn Ruby process: ${err.message}`));
142
501
  });
143
502
  });
@@ -157,14 +516,13 @@ Error: ${e}`));
157
516
  "puts Opal::Vite::Compiler.runtime_code"
158
517
  ];
159
518
  } else {
519
+ const gemLibPath = this.resolveGemLibPath();
160
520
  command = "ruby";
161
521
  args = [
162
522
  "-I",
163
- this.resolveGemLibPath(),
164
- "-r",
165
- "opal-vite",
523
+ gemLibPath,
166
524
  "-e",
167
- "puts Opal::Vite::Compiler.runtime_code"
525
+ `$LOAD_PATH.unshift('${gemLibPath}'); require 'opal-vite'; puts Opal::Vite::Compiler.runtime_code`
168
526
  ];
169
527
  }
170
528
  const ruby = spawn(command, args, {
@@ -194,15 +552,16 @@ ${stderr}`));
194
552
  getCompilerScript() {
195
553
  const includeConcerns = this.options.includeConcerns;
196
554
  const sourceMap = this.options.sourceMap;
555
+ const stubs = JSON.stringify(this.options.stubs);
197
556
  return `
198
- require 'opal-vite'
199
557
  file_path = ARGV[0]
200
- Opal::Vite.compile_for_vite(file_path, include_concerns: ${includeConcerns}, source_map: ${sourceMap})
558
+ stubs = ${stubs}
559
+ Opal::Vite.compile_for_vite(file_path, include_concerns: ${includeConcerns}, source_map: ${sourceMap}, stubs: stubs)
201
560
  `.trim();
202
561
  }
203
562
  resolveGemLibPath() {
204
563
  if (this.options.gemPath.startsWith(".") || this.options.gemPath.startsWith("/")) {
205
- return path2.resolve(this.options.gemPath, "lib");
564
+ return path.resolve(this.options.gemPath, "lib");
206
565
  }
207
566
  return this.options.gemPath;
208
567
  }
@@ -277,7 +636,7 @@ var OpalResolver = class {
277
636
  }
278
637
  }
279
638
  async resolveAbsolute(id) {
280
- if (!path2.isAbsolute(id)) {
639
+ if (!path.isAbsolute(id)) {
281
640
  return null;
282
641
  }
283
642
  if (await this.fileExists(id)) {
@@ -295,8 +654,8 @@ var OpalResolver = class {
295
654
  if (!id.startsWith(".") || !importer) {
296
655
  return null;
297
656
  }
298
- const importerDir = path2.dirname(importer);
299
- const resolved = path2.resolve(importerDir, id);
657
+ const importerDir = path.dirname(importer);
658
+ const resolved = path.resolve(importerDir, id);
300
659
  if (await this.fileExists(resolved)) {
301
660
  return resolved;
302
661
  }
@@ -311,15 +670,15 @@ var OpalResolver = class {
311
670
  async resolveFromLoadPaths(id) {
312
671
  const baseId = id.endsWith(".rb") ? id.slice(0, -3) : id;
313
672
  for (const loadPath of this.loadPaths) {
314
- const fullPath = path2.resolve(loadPath, id);
673
+ const fullPath = path.resolve(loadPath, id);
315
674
  if (await this.fileExists(fullPath)) {
316
675
  return fullPath;
317
676
  }
318
- const withExt = path2.resolve(loadPath, `${baseId}.rb`);
677
+ const withExt = path.resolve(loadPath, `${baseId}.rb`);
319
678
  if (await this.fileExists(withExt)) {
320
679
  return withExt;
321
680
  }
322
- const indexPath = path2.resolve(loadPath, baseId, "index.rb");
681
+ const indexPath = path.resolve(loadPath, baseId, "index.rb");
323
682
  if (await this.fileExists(indexPath)) {
324
683
  return indexPath;
325
684
  }
@@ -335,7 +694,7 @@ var OpalResolver = class {
335
694
  }
336
695
  }
337
696
  hasExtension(filePath) {
338
- const ext = path2.extname(filePath);
697
+ const ext = path.extname(filePath);
339
698
  return ext !== "";
340
699
  }
341
700
  };
@@ -368,7 +727,7 @@ var OpalHMRManager = class {
368
727
  });
369
728
  this.watcher.on("unlink", (filePath) => {
370
729
  this.log(`File removed: ${filePath}`);
371
- const absolutePath = path2.resolve(this.server.config.root, filePath);
730
+ const absolutePath = path.resolve(this.server.config.root, filePath);
372
731
  this.compiler.clearCache(absolutePath);
373
732
  this.resolver.clearCache(absolutePath);
374
733
  this.dependencyGraph.delete(absolutePath);
@@ -392,7 +751,7 @@ var OpalHMRManager = class {
392
751
  * Handle file change and trigger HMR update
393
752
  */
394
753
  async handleFileChange(filePath) {
395
- const absolutePath = path2.resolve(this.server.config.root, filePath);
754
+ const absolutePath = path.resolve(this.server.config.root, filePath);
396
755
  this.log(`File changed: ${filePath}`);
397
756
  try {
398
757
  this.compiler.clearCache(absolutePath);
@@ -607,6 +966,12 @@ ${html}`;
607
966
  hmrManager.cleanup();
608
967
  }
609
968
  };
969
+ },
970
+ // Print metrics after build completes
971
+ closeBundle() {
972
+ if (options.metrics) {
973
+ compiler.printMetricsSummary();
974
+ }
610
975
  }
611
976
  };
612
977
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/compiler.ts","../src/resolver.ts","../src/hmr.ts","../src/index.ts"],"names":["path","stat","resolve","fs2","path3"],"mappings":"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","file":"index.js","sourcesContent":["import { spawn } from 'child_process'\nimport * as fs from 'fs/promises'\nimport { accessSync } from 'fs'\nimport * as path from 'path'\nimport type { OpalPluginOptions, CompileResult, CacheEntry } from './types'\n\nexport class OpalCompiler {\n private options: Required<OpalPluginOptions>\n private cache: Map<string, CacheEntry> = new Map()\n private runtimeCache: string | null = null\n private useBundler: boolean\n\n constructor(options: OpalPluginOptions = {}) {\n this.options = {\n gemPath: options.gemPath || 'opal-vite',\n sourceMap: options.sourceMap !== false,\n loadPaths: options.loadPaths || ['./src'],\n arityCheck: options.arityCheck || false,\n freezing: options.freezing !== false,\n debug: options.debug || false,\n useBundler: options.useBundler !== undefined ? options.useBundler : this.detectGemfile(),\n includeConcerns: options.includeConcerns !== false\n }\n this.useBundler = this.options.useBundler\n\n if (this.options.debug) {\n console.log(`[vite-plugin-opal] Using bundler: ${this.useBundler}`)\n console.log(`[vite-plugin-opal] Working directory: ${process.cwd()}`)\n console.log(`[vite-plugin-opal] Include concerns: ${this.options.includeConcerns}`)\n }\n }\n\n private detectGemfile(): boolean {\n try {\n const gemfilePath = path.join(process.cwd(), 'Gemfile')\n accessSync(gemfilePath)\n return true\n } catch {\n return false\n }\n }\n\n async compile(filePath: string): Promise<CompileResult> {\n // Check cache\n const cached = this.cache.get(filePath)\n if (cached) {\n try {\n const stat = await fs.stat(filePath)\n if (stat.mtimeMs <= cached.mtime) {\n this.log(`Cache hit: ${filePath}`)\n return {\n code: cached.code,\n map: cached.map,\n dependencies: cached.dependencies\n }\n }\n } catch (e) {\n // File might have been deleted, remove from cache\n this.cache.delete(filePath)\n }\n }\n\n // Compile\n this.log(`Compiling: ${filePath}`)\n const result = await this.compileViaRuby(filePath)\n\n // Cache the result\n try {\n const stat = await fs.stat(filePath)\n this.cache.set(filePath, {\n ...result,\n mtime: stat.mtimeMs\n })\n } catch (e) {\n // Ignore if we can't stat the file\n }\n\n return result\n }\n\n async getOpalRuntime(): Promise<string> {\n if (this.runtimeCache) {\n return this.runtimeCache\n }\n\n this.log('Loading Opal runtime')\n const runtime = await this.getRuntimeViaRuby()\n this.runtimeCache = runtime\n return runtime\n }\n\n clearCache(filePath?: string): void {\n if (filePath) {\n this.cache.delete(filePath)\n this.log(`Cache cleared: ${filePath}`)\n } else {\n this.cache.clear()\n this.log('Cache cleared (all)')\n }\n }\n\n private async compileViaRuby(filePath: string): Promise<CompileResult> {\n return new Promise((resolve, reject) => {\n let command: string\n let args: string[]\n\n if (this.useBundler) {\n command = 'bundle'\n args = [\n 'exec', 'ruby',\n '-r', 'opal-vite',\n '-e', this.getCompilerScript(),\n filePath\n ]\n } else {\n command = 'ruby'\n args = [\n '-I', this.resolveGemLibPath(),\n '-r', 'opal-vite',\n '-e', this.getCompilerScript(),\n filePath\n ]\n }\n\n this.log(`Spawning Ruby: ${command} ${args.join(' ')}`)\n\n const ruby = spawn(command, args, {\n cwd: process.cwd()\n })\n\n let stdout = ''\n let stderr = ''\n\n ruby.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n\n ruby.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n\n ruby.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Opal compilation failed:\\n${stderr}`))\n return\n }\n\n try {\n const result = JSON.parse(stdout)\n resolve(result)\n } catch (e) {\n reject(new Error(`Failed to parse compiler output:\\n${stdout}\\n\\nError: ${e}`))\n }\n })\n\n ruby.on('error', (err) => {\n reject(new Error(`Failed to spawn Ruby process: ${err.message}`))\n })\n })\n }\n\n private async getRuntimeViaRuby(): Promise<string> {\n return new Promise((resolve, reject) => {\n let command: string\n let args: string[]\n\n if (this.useBundler) {\n command = 'bundle'\n args = [\n 'exec', 'ruby',\n '-r', 'opal-vite',\n '-e', 'puts Opal::Vite::Compiler.runtime_code'\n ]\n } else {\n command = 'ruby'\n args = [\n '-I', this.resolveGemLibPath(),\n '-r', 'opal-vite',\n '-e', 'puts Opal::Vite::Compiler.runtime_code'\n ]\n }\n\n const ruby = spawn(command, args, {\n cwd: process.cwd()\n })\n\n let stdout = ''\n let stderr = ''\n\n ruby.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n\n ruby.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n\n ruby.on('close', (code) => {\n if (code === 0) {\n resolve(stdout)\n } else {\n reject(new Error(`Failed to get Opal runtime:\\n${stderr}`))\n }\n })\n\n ruby.on('error', (err) => {\n reject(new Error(`Failed to spawn Ruby process: ${err.message}`))\n })\n })\n }\n\n private getCompilerScript(): string {\n const includeConcerns = this.options.includeConcerns\n const sourceMap = this.options.sourceMap\n return `\n require 'opal-vite'\n file_path = ARGV[0]\n Opal::Vite.compile_for_vite(file_path, include_concerns: ${includeConcerns}, source_map: ${sourceMap})\n `.trim()\n }\n\n private resolveGemLibPath(): string {\n // Try to resolve the gem path\n // In development, this points to our local gem\n // In production, bundler will handle it\n if (this.options.gemPath.startsWith('.') || this.options.gemPath.startsWith('/')) {\n return path.resolve(this.options.gemPath, 'lib')\n }\n return this.options.gemPath\n }\n\n private log(message: string): void {\n if (this.options.debug) {\n console.log(`[vite-plugin-opal] ${message}`)\n }\n }\n}\n","import * as path from 'path'\nimport * as fs from 'fs/promises'\nimport type { OpalPluginOptions } from './types'\n\nexport class OpalResolver {\n private options: Required<OpalPluginOptions>\n private loadPaths: string[]\n private resolveCache: Map<string, string | null> = new Map()\n\n constructor(options: OpalPluginOptions = {}) {\n this.options = {\n gemPath: options.gemPath || 'opal-vite',\n sourceMap: options.sourceMap !== false,\n loadPaths: options.loadPaths || ['./src'],\n arityCheck: options.arityCheck || false,\n freezing: options.freezing !== false,\n debug: options.debug || false\n }\n this.loadPaths = this.options.loadPaths\n }\n\n /**\n * Resolve a Ruby file import\n * Supports:\n * - Absolute paths: /path/to/file.rb\n * - Relative paths: ./file.rb, ../file.rb\n * - Load path resolution: file (searches in loadPaths)\n */\n async resolve(id: string, importer?: string): Promise<string | null> {\n // Check cache first\n const cacheKey = `${id}|${importer || ''}`\n if (this.resolveCache.has(cacheKey)) {\n return this.resolveCache.get(cacheKey)!\n }\n\n let resolved: string | null = null\n\n // Only resolve .rb files or files without extension\n if (id.endsWith('.rb') || !this.hasExtension(id)) {\n // Try different resolution strategies\n resolved = await this.resolveAbsolute(id) ||\n await this.resolveRelative(id, importer) ||\n await this.resolveFromLoadPaths(id)\n }\n\n // Cache the result\n this.resolveCache.set(cacheKey, resolved)\n\n if (resolved && this.options.debug) {\n console.log(`[vite-plugin-opal] Resolved: ${id} -> ${resolved}`)\n }\n\n return resolved\n }\n\n /**\n * Clear the resolution cache\n */\n clearCache(filePath?: string): void {\n if (filePath) {\n // Clear cache entries related to this file\n for (const [key, value] of this.resolveCache.entries()) {\n if (value === filePath || key.startsWith(filePath)) {\n this.resolveCache.delete(key)\n }\n }\n } else {\n this.resolveCache.clear()\n }\n }\n\n /**\n * Get all load paths\n */\n getLoadPaths(): string[] {\n return [...this.loadPaths]\n }\n\n /**\n * Add a load path\n */\n addLoadPath(loadPath: string): void {\n if (!this.loadPaths.includes(loadPath)) {\n this.loadPaths.push(loadPath)\n this.clearCache() // Clear cache when load paths change\n }\n }\n\n private async resolveAbsolute(id: string): Promise<string | null> {\n if (!path.isAbsolute(id)) {\n return null\n }\n\n // Try as-is\n if (await this.fileExists(id)) {\n return id\n }\n\n // Try with .rb extension\n if (!id.endsWith('.rb')) {\n const withExt = `${id}.rb`\n if (await this.fileExists(withExt)) {\n return withExt\n }\n }\n\n return null\n }\n\n private async resolveRelative(id: string, importer?: string): Promise<string | null> {\n if (!id.startsWith('.') || !importer) {\n return null\n }\n\n const importerDir = path.dirname(importer)\n const resolved = path.resolve(importerDir, id)\n\n // Try as-is\n if (await this.fileExists(resolved)) {\n return resolved\n }\n\n // Try with .rb extension\n if (!id.endsWith('.rb')) {\n const withExt = `${resolved}.rb`\n if (await this.fileExists(withExt)) {\n return withExt\n }\n }\n\n return null\n }\n\n private async resolveFromLoadPaths(id: string): Promise<string | null> {\n // Remove .rb extension for load path search\n const baseId = id.endsWith('.rb') ? id.slice(0, -3) : id\n\n for (const loadPath of this.loadPaths) {\n // Try with original id\n const fullPath = path.resolve(loadPath, id)\n if (await this.fileExists(fullPath)) {\n return fullPath\n }\n\n // Try with .rb extension\n const withExt = path.resolve(loadPath, `${baseId}.rb`)\n if (await this.fileExists(withExt)) {\n return withExt\n }\n\n // Try as a directory with index.rb\n const indexPath = path.resolve(loadPath, baseId, 'index.rb')\n if (await this.fileExists(indexPath)) {\n return indexPath\n }\n }\n\n return null\n }\n\n private async fileExists(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath)\n return stat.isFile()\n } catch {\n return false\n }\n }\n\n private hasExtension(filePath: string): boolean {\n const ext = path.extname(filePath)\n return ext !== ''\n }\n}\n","import type { ViteDevServer, ModuleNode, Update } from 'vite'\nimport type { OpalCompiler } from './compiler'\nimport type { OpalResolver } from './resolver'\nimport type { OpalPluginOptions } from './types'\nimport * as path from 'path'\nimport * as chokidar from 'chokidar'\n\nexport interface HMRManager {\n setup(): void\n cleanup(): void\n handleFileChange(filePath: string): Promise<void>\n}\n\nexport class OpalHMRManager implements HMRManager {\n private server: ViteDevServer\n private compiler: OpalCompiler\n private resolver: OpalResolver\n private options: OpalPluginOptions\n private watcher?: chokidar.FSWatcher\n private dependencyGraph: Map<string, Set<string>> = new Map()\n\n constructor(\n server: ViteDevServer,\n compiler: OpalCompiler,\n resolver: OpalResolver,\n options: OpalPluginOptions\n ) {\n this.server = server\n this.compiler = compiler\n this.resolver = resolver\n this.options = options\n }\n\n /**\n * Setup HMR file watching\n */\n setup(): void {\n this.log('Setting up HMR for .rb files')\n\n // Watch .rb files for changes\n this.watcher = chokidar.watch('**/*.rb', {\n ignored: /node_modules/,\n persistent: true,\n cwd: this.server.config.root,\n ignoreInitial: true // Don't trigger on initial scan\n })\n\n this.watcher.on('change', async (filePath: string) => {\n await this.handleFileChange(filePath)\n })\n\n this.watcher.on('add', async (filePath: string) => {\n this.log(`New file detected: ${filePath}`)\n await this.handleFileChange(filePath)\n })\n\n this.watcher.on('unlink', (filePath: string) => {\n this.log(`File removed: ${filePath}`)\n const absolutePath = path.resolve(this.server.config.root, filePath)\n this.compiler.clearCache(absolutePath)\n this.resolver.clearCache(absolutePath)\n this.dependencyGraph.delete(absolutePath)\n })\n\n // Cleanup on server close\n this.server.httpServer?.on('close', () => {\n this.cleanup()\n })\n\n this.log('HMR setup complete')\n }\n\n /**\n * Cleanup resources\n */\n cleanup(): void {\n if (this.watcher) {\n this.log('Cleaning up HMR watcher')\n this.watcher.close()\n this.watcher = undefined\n }\n }\n\n /**\n * Handle file change and trigger HMR update\n */\n async handleFileChange(filePath: string): Promise<void> {\n const absolutePath = path.resolve(this.server.config.root, filePath)\n\n this.log(`File changed: ${filePath}`)\n\n try {\n // Clear caches for the changed file\n this.compiler.clearCache(absolutePath)\n this.resolver.clearCache(absolutePath)\n\n // Get the module from the module graph\n const module = this.server.moduleGraph.getModuleById(absolutePath)\n\n if (!module) {\n this.log(`Module not found in graph: ${filePath}`, 'warn')\n return\n }\n\n // Collect all modules that need to be updated\n const modulesToUpdate = new Set<ModuleNode>([module])\n\n // Find dependent modules (modules that import this one)\n await this.collectDependentModules(module, modulesToUpdate)\n\n // Invalidate all affected modules\n for (const mod of modulesToUpdate) {\n this.server.moduleGraph.invalidateModule(mod)\n this.log(`Invalidated: ${mod.url}`)\n }\n\n // Build HMR updates\n const updates: Update[] = Array.from(modulesToUpdate).map(mod => ({\n type: 'js-update' as const,\n path: mod.url,\n acceptedPath: mod.url,\n timestamp: Date.now()\n }))\n\n // Send HMR update to browser\n this.server.ws.send({\n type: 'update',\n updates\n })\n\n this.log(`✓ HMR update sent for ${updates.length} module(s)`, 'success')\n } catch (error) {\n this.handleError(filePath, error)\n }\n }\n\n /**\n * Collect all modules that depend on the given module\n */\n private async collectDependentModules(\n module: ModuleNode,\n result: Set<ModuleNode>\n ): Promise<void> {\n // Get modules that import this module\n for (const importer of module.importers) {\n if (!result.has(importer)) {\n result.add(importer)\n // Recursively collect their dependents\n await this.collectDependentModules(importer, result)\n }\n }\n }\n\n /**\n * Handle compilation or HMR errors\n */\n private handleError(filePath: string, error: unknown): void {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n this.log(`Error processing ${filePath}: ${errorMessage}`, 'error')\n\n // Send error overlay to browser\n this.server.ws.send({\n type: 'error',\n err: {\n message: `Opal compilation failed for ${filePath}`,\n stack: error instanceof Error ? error.stack : undefined,\n id: filePath,\n frame: this.extractErrorFrame(errorMessage),\n plugin: 'vite-plugin-opal',\n loc: this.extractErrorLocation(errorMessage)\n }\n })\n }\n\n /**\n * Extract error frame from error message\n */\n private extractErrorFrame(errorMessage: string): string | undefined {\n // Try to extract relevant code frame from error\n const lines = errorMessage.split('\\n')\n const relevantLines = lines.slice(0, 10).join('\\n')\n return relevantLines || undefined\n }\n\n /**\n * Extract error location from error message\n */\n private extractErrorLocation(errorMessage: string): { file?: string; line?: number; column?: number } | undefined {\n // Try to parse location from Opal error messages\n // Example: \"file.rb:10:5: error message\"\n const match = errorMessage.match(/(.+):(\\d+):(\\d+)/)\n if (match) {\n return {\n file: match[1],\n line: parseInt(match[2], 10),\n column: parseInt(match[3], 10)\n }\n }\n return undefined\n }\n\n /**\n * Log HMR messages\n */\n private log(message: string, level: 'info' | 'warn' | 'error' | 'success' = 'info'): void {\n if (!this.options.debug && level === 'info') {\n return\n }\n\n const prefix = '[vite-plugin-opal:hmr]'\n const timestamp = new Date().toLocaleTimeString()\n\n const colors = {\n info: '\\x1b[36m', // Cyan\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n success: '\\x1b[32m' // Green\n }\n const reset = '\\x1b[0m'\n\n const color = colors[level]\n const levelText = level.toUpperCase().padEnd(7)\n\n console.log(`${color}${prefix} ${timestamp} [${levelText}]${reset} ${message}`)\n }\n\n /**\n * Get dependency graph information (for debugging)\n */\n getDependencyGraph(): Map<string, Set<string>> {\n return new Map(this.dependencyGraph)\n }\n}\n","import type { Plugin, ViteDevServer } from 'vite'\nimport { OpalCompiler } from './compiler'\nimport { OpalResolver } from './resolver'\nimport { OpalHMRManager } from './hmr'\nimport type { OpalPluginOptions } from './types'\nimport * as path from 'path'\n\nconst VIRTUAL_RUNTIME_ID = '/@opal-runtime'\nconst VIRTUAL_RUNTIME_PREFIX = '\\0' + VIRTUAL_RUNTIME_ID\n\n/**\n * Vite plugin for compiling Ruby files to JavaScript using Opal.\n *\n * @param options - Plugin configuration options\n * @returns Vite plugin instance\n *\n * @example\n * ```ts\n * import { defineConfig } from 'vite'\n * import opal from 'vite-plugin-opal'\n *\n * export default defineConfig({\n * plugins: [\n * opal({\n * loadPaths: ['./app/opal'],\n * sourceMap: true\n * })\n * ]\n * })\n * ```\n *\n * @see {@link OpalPluginOptions} for all available options\n */\nexport default function opalPlugin(options: OpalPluginOptions = {}): Plugin {\n const compiler = new OpalCompiler(options)\n const resolver = new OpalResolver(options)\n let server: ViteDevServer | undefined\n let hmrManager: OpalHMRManager | undefined\n let isBuild = false\n\n return {\n name: 'vite-plugin-opal',\n enforce: 'pre', // Run before other plugins\n\n // Detect build vs serve mode\n config(_config, { command }) {\n isBuild = command === 'build'\n },\n\n // Mark .rb files as valid imports\n async resolveId(id: string, importer?: string) {\n // Handle virtual runtime module\n if (id === VIRTUAL_RUNTIME_ID) {\n if (options.debug) {\n console.log(`[vite-plugin-opal] Resolved virtual runtime: ${VIRTUAL_RUNTIME_PREFIX}`)\n }\n return VIRTUAL_RUNTIME_PREFIX\n }\n\n // Handle .rb files and files without extension (Opal style requires)\n if (id.endsWith('.rb') || (!id.includes('.') && !id.startsWith('/'))) {\n const resolved = await resolver.resolve(id, importer)\n if (options.debug) {\n console.log(`[vite-plugin-opal] resolveId: ${id} -> ${resolved}`)\n }\n return resolved\n }\n\n return null\n },\n\n // Load and compile .rb files\n async load(id: string) {\n // Handle virtual runtime module\n if (id === VIRTUAL_RUNTIME_PREFIX) {\n if (options.debug) {\n console.log(`[vite-plugin-opal] Loading Opal runtime...`)\n }\n const runtime = await compiler.getOpalRuntime()\n if (options.debug) {\n console.log(`[vite-plugin-opal] Opal runtime loaded: ${runtime.length} bytes`)\n }\n return {\n code: runtime,\n map: null\n }\n }\n\n // Handle .rb files\n if (id.endsWith('.rb')) {\n if (options.debug) {\n console.log(`[vite-plugin-opal] load: Compiling ${id}`)\n }\n try {\n const result = await compiler.compile(id)\n if (options.debug) {\n console.log(`[vite-plugin-opal] load: Compiled ${id} -> ${result.code.length} bytes`)\n console.log(`[vite-plugin-opal] load: Source map: ${result.map ? 'yes' : 'no'}`)\n }\n const sourceMap = result.map ? JSON.parse(result.map) : null\n if (options.debug && sourceMap) {\n console.log(`[vite-plugin-opal] load: Source map version: ${sourceMap.version}, sections: ${sourceMap.sections?.length || 0}`)\n }\n return {\n code: result.code,\n map: sourceMap\n }\n } catch (error) {\n console.error(`[vite-plugin-opal] Compilation error for ${id}:`, error)\n this.error(error instanceof Error ? error.message : String(error))\n }\n }\n\n return null\n },\n\n // Auto-inject Opal runtime into HTML (development only)\n transformIndexHtml(html: string) {\n // Skip injection during build - runtime is bundled into JS\n if (isBuild) {\n return html\n }\n\n // Inject runtime before closing </head> tag (development only)\n const runtimeScript = `<script type=\"module\" src=\"${VIRTUAL_RUNTIME_ID}\"></script>`\n\n if (html.includes('</head>')) {\n return html.replace('</head>', ` ${runtimeScript}\\n</head>`)\n } else if (html.includes('<head>')) {\n return html.replace('<head>', `<head>\\n ${runtimeScript}`)\n } else {\n // No head tag, inject at the beginning\n return `${runtimeScript}\\n${html}`\n }\n },\n\n // Setup HMR for .rb files\n configureServer(_server: ViteDevServer) {\n server = _server\n\n // Initialize HMR manager\n hmrManager = new OpalHMRManager(server, compiler, resolver, options)\n hmrManager.setup()\n\n return () => {\n // Cleanup function called when server closes\n if (hmrManager) {\n hmrManager.cleanup()\n }\n }\n }\n }\n}\n\nexport type { OpalPluginOptions } from './types'\n"]}
1
+ {"version":3,"sources":["../src/compiler.ts","../src/resolver.ts","../src/hmr.ts","../src/index.ts"],"names":["stat","resolve","path2","fs2","path3"],"mappings":"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","file":"index.js","sourcesContent":["import { spawn } from 'child_process'\nimport * as fs from 'fs/promises'\nimport { accessSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'\nimport * as path from 'path'\nimport * as crypto from 'crypto'\nimport type { OpalPluginOptions, CompileResult, CacheEntry, OpalCompilationError } from './types'\n\n/**\n * Parse Opal/Ruby compilation error output into structured error information\n */\nfunction parseRubyError(stderr: string, filePath: string): OpalCompilationError {\n const lines = stderr.trim().split('\\n')\n const error: OpalCompilationError = {\n message: stderr.trim(),\n file: filePath,\n rawOutput: stderr\n }\n\n // Try to extract line number from Ruby error format: \"file.rb:123: error message\"\n // or \"file.rb:123:in `method': error message\"\n for (const line of lines) {\n const lineMatch = line.match(/^(.+?):(\\d+)(?::(\\d+))?(?::in `[^']+')?\\s*[:\\-]?\\s*(.*)/)\n if (lineMatch) {\n const [, matchedFile, lineNum, colNum, msg] = lineMatch\n if (matchedFile.endsWith('.rb') || matchedFile.includes(filePath)) {\n error.file = matchedFile\n error.line = parseInt(lineNum, 10)\n if (colNum) {\n error.column = parseInt(colNum, 10)\n }\n error.message = msg || line\n break\n }\n }\n }\n\n // Extract error type from Ruby exceptions\n const typeMatch = stderr.match(/(\\w+Error|\\w+Exception):\\s*(.+)/m)\n if (typeMatch) {\n error.errorType = typeMatch[1]\n if (!error.message || error.message === stderr.trim()) {\n error.message = typeMatch[2].trim()\n }\n }\n\n // Check for common Opal-specific errors\n if (stderr.includes('SyntaxError')) {\n error.errorType = 'SyntaxError'\n const syntaxMatch = stderr.match(/SyntaxError:\\s*(.+?)(?:\\n|$)/)\n if (syntaxMatch) {\n error.message = syntaxMatch[1]\n }\n } else if (stderr.includes('NameError')) {\n error.errorType = 'NameError'\n const nameMatch = stderr.match(/NameError:\\s*(.+?)(?:\\n|$)/)\n if (nameMatch) {\n error.message = nameMatch[1]\n }\n } else if (stderr.includes('LoadError')) {\n error.errorType = 'LoadError'\n const loadMatch = stderr.match(/LoadError:\\s*(.+?)(?:\\n|$)/)\n if (loadMatch) {\n error.message = loadMatch[1]\n }\n // Extract the file that couldn't be loaded\n const requireMatch = stderr.match(/cannot load such file\\s*--\\s*(.+)/)\n if (requireMatch) {\n error.hint = `Check that '${requireMatch[1]}' exists and is in your load paths`\n }\n }\n\n return error\n}\n\n/**\n * Format compilation error for display in terminal/browser\n */\nfunction formatCompilationError(error: OpalCompilationError): string {\n const parts: string[] = []\n\n // Header with error type\n const errorType = error.errorType || 'CompilationError'\n parts.push(`\\x1b[31m✖ Opal ${errorType}\\x1b[0m`)\n\n // Location info\n if (error.file) {\n let location = ` \\x1b[36m→ ${error.file}\\x1b[0m`\n if (error.line) {\n location += `\\x1b[33m:${error.line}\\x1b[0m`\n if (error.column) {\n location += `\\x1b[33m:${error.column}\\x1b[0m`\n }\n }\n parts.push(location)\n }\n\n // Error message\n parts.push(` \\x1b[37m${error.message}\\x1b[0m`)\n\n // Hint if available\n if (error.hint) {\n parts.push(` \\x1b[33m💡 ${error.hint}\\x1b[0m`)\n }\n\n return parts.join('\\n')\n}\n\n/**\n * Metrics for a single compilation\n */\ninterface CompileMetrics {\n file: string\n duration: number\n cacheHit: boolean\n source: 'memory' | 'disk' | 'compile'\n}\n\n/**\n * Disk cache entry format\n */\ninterface DiskCacheEntry {\n version: string\n contentHash: string\n mtime: number\n result: CompileResult\n}\n\nconst CACHE_VERSION = '1.0.0'\n\nexport class OpalCompiler {\n private options: Required<OpalPluginOptions>\n private cache: Map<string, CacheEntry> = new Map()\n private runtimeCache: string | null = null\n private useBundler: boolean\n private cacheDir: string\n private metrics: CompileMetrics[] = []\n private compilationQueue: Promise<void> = Promise.resolve()\n private activeCompilations = 0\n\n constructor(options: OpalPluginOptions = {}) {\n this.options = {\n gemPath: options.gemPath || 'opal-vite',\n sourceMap: options.sourceMap !== false,\n loadPaths: options.loadPaths || ['./src'],\n arityCheck: options.arityCheck || false,\n freezing: options.freezing !== false,\n debug: options.debug || false,\n useBundler: options.useBundler !== undefined ? options.useBundler : this.detectGemfile(),\n includeConcerns: options.includeConcerns !== false,\n diskCache: options.diskCache !== false,\n cacheDir: options.cacheDir || '',\n stubs: options.stubs || [],\n parallelCompilation: options.parallelCompilation || 4,\n metrics: options.metrics || false\n }\n this.useBundler = this.options.useBundler\n this.cacheDir = this.resolveCacheDir()\n\n // Ensure cache directory exists\n if (this.options.diskCache) {\n this.ensureCacheDir()\n }\n\n if (this.options.debug) {\n console.log(`[vite-plugin-opal] Using bundler: ${this.useBundler}`)\n console.log(`[vite-plugin-opal] Working directory: ${process.cwd()}`)\n console.log(`[vite-plugin-opal] Include concerns: ${this.options.includeConcerns}`)\n console.log(`[vite-plugin-opal] Disk cache: ${this.options.diskCache ? 'enabled' : 'disabled'}`)\n if (this.options.diskCache) {\n console.log(`[vite-plugin-opal] Cache directory: ${this.cacheDir}`)\n }\n if (this.options.stubs.length > 0) {\n console.log(`[vite-plugin-opal] Stubs: ${this.options.stubs.join(', ')}`)\n }\n console.log(`[vite-plugin-opal] Parallel compilation: ${this.options.parallelCompilation}`)\n }\n }\n\n private resolveCacheDir(): string {\n if (this.options.cacheDir) {\n return path.resolve(process.cwd(), this.options.cacheDir)\n }\n // Default: node_modules/.cache/opal-vite\n return path.resolve(process.cwd(), 'node_modules', '.cache', 'opal-vite')\n }\n\n private ensureCacheDir(): void {\n try {\n if (!existsSync(this.cacheDir)) {\n mkdirSync(this.cacheDir, { recursive: true })\n this.log(`Created cache directory: ${this.cacheDir}`)\n }\n } catch (e) {\n this.log(`Warning: Could not create cache directory: ${e}`)\n }\n }\n\n private getCacheKey(filePath: string): string {\n // Create a safe filename from the file path\n const normalized = path.resolve(filePath)\n return crypto.createHash('md5').update(normalized).digest('hex')\n }\n\n private getContentHash(content: string): string {\n return crypto.createHash('md5').update(content).digest('hex')\n }\n\n private getDiskCachePath(filePath: string): string {\n return path.join(this.cacheDir, `${this.getCacheKey(filePath)}.json`)\n }\n\n private async loadFromDiskCache(filePath: string, contentHash: string): Promise<CompileResult | null> {\n if (!this.options.diskCache) return null\n\n const cachePath = this.getDiskCachePath(filePath)\n try {\n if (!existsSync(cachePath)) return null\n\n const cacheContent = readFileSync(cachePath, 'utf-8')\n const entry: DiskCacheEntry = JSON.parse(cacheContent)\n\n // Validate cache entry\n if (entry.version !== CACHE_VERSION) {\n this.log(`Disk cache version mismatch for ${filePath}`)\n return null\n }\n\n if (entry.contentHash !== contentHash) {\n this.log(`Disk cache content hash mismatch for ${filePath}`)\n return null\n }\n\n this.log(`Disk cache hit: ${filePath}`)\n return entry.result\n } catch (e) {\n // Cache file is invalid or corrupted\n this.log(`Disk cache read error for ${filePath}: ${e}`)\n return null\n }\n }\n\n private saveToDiskCache(filePath: string, contentHash: string, mtime: number, result: CompileResult): void {\n if (!this.options.diskCache) return\n\n const cachePath = this.getDiskCachePath(filePath)\n try {\n const entry: DiskCacheEntry = {\n version: CACHE_VERSION,\n contentHash,\n mtime,\n result\n }\n writeFileSync(cachePath, JSON.stringify(entry), 'utf-8')\n this.log(`Disk cache saved: ${filePath}`)\n } catch (e) {\n this.log(`Disk cache write error for ${filePath}: ${e}`)\n }\n }\n\n private detectGemfile(): boolean {\n try {\n const gemfilePath = path.join(process.cwd(), 'Gemfile')\n accessSync(gemfilePath)\n return true\n } catch {\n return false\n }\n }\n\n async compile(filePath: string): Promise<CompileResult> {\n const startTime = this.options.metrics ? performance.now() : 0\n\n // Check if this is a stubbed module\n const stubResult = this.checkStub(filePath)\n if (stubResult) {\n this.recordMetrics(filePath, startTime, true, 'memory')\n return stubResult\n }\n\n // Read file content for hash-based cache validation\n let fileContent: string\n let stat: { mtimeMs: number }\n try {\n fileContent = await fs.readFile(filePath, 'utf-8')\n stat = await fs.stat(filePath)\n } catch (e) {\n throw new Error(`Failed to read file: ${filePath}`)\n }\n\n const contentHash = this.getContentHash(fileContent)\n\n // Check memory cache first\n const cached = this.cache.get(filePath)\n if (cached) {\n if (stat.mtimeMs <= cached.mtime) {\n this.log(`Memory cache hit: ${filePath}`)\n this.recordMetrics(filePath, startTime, true, 'memory')\n return {\n code: cached.code,\n map: cached.map,\n dependencies: cached.dependencies\n }\n }\n // Cache is stale, remove it\n this.cache.delete(filePath)\n }\n\n // Check disk cache\n const diskCached = await this.loadFromDiskCache(filePath, contentHash)\n if (diskCached) {\n // Update memory cache\n this.cache.set(filePath, {\n ...diskCached,\n mtime: stat.mtimeMs\n })\n this.recordMetrics(filePath, startTime, true, 'disk')\n return diskCached\n }\n\n // Compile with concurrency control\n this.log(`Compiling: ${filePath}`)\n const result = await this.compileWithConcurrencyControl(filePath)\n\n // Cache the result in memory\n this.cache.set(filePath, {\n ...result,\n mtime: stat.mtimeMs\n })\n\n // Cache the result on disk\n this.saveToDiskCache(filePath, contentHash, stat.mtimeMs, result)\n\n this.recordMetrics(filePath, startTime, false, 'compile')\n return result\n }\n\n /**\n * Compile multiple files in parallel with concurrency control\n */\n async compileMany(filePaths: string[]): Promise<Map<string, CompileResult>> {\n const results = new Map<string, CompileResult>()\n\n // Process files in batches based on parallelCompilation setting\n const batchSize = this.options.parallelCompilation\n for (let i = 0; i < filePaths.length; i += batchSize) {\n const batch = filePaths.slice(i, i + batchSize)\n const batchResults = await Promise.all(\n batch.map(async (filePath) => {\n try {\n const result = await this.compile(filePath)\n return { filePath, result, error: null }\n } catch (e) {\n return { filePath, result: null, error: e }\n }\n })\n )\n\n for (const { filePath, result, error } of batchResults) {\n if (result) {\n results.set(filePath, result)\n } else {\n this.log(`Compilation failed for ${filePath}: ${error}`)\n }\n }\n }\n\n return results\n }\n\n private async compileWithConcurrencyControl(filePath: string): Promise<CompileResult> {\n // Wait if we're at the concurrency limit\n while (this.activeCompilations >= this.options.parallelCompilation) {\n await new Promise(resolve => setTimeout(resolve, 10))\n }\n\n this.activeCompilations++\n try {\n return await this.compileViaRuby(filePath)\n } finally {\n this.activeCompilations--\n }\n }\n\n private checkStub(filePath: string): CompileResult | null {\n if (this.options.stubs.length === 0) return null\n\n const fileName = path.basename(filePath, '.rb')\n const isStubbed = this.options.stubs.some(stub => {\n // Match exact name or pattern\n if (stub === fileName) return true\n // Match as a path component (e.g., 'active_support' matches any active_support/*.rb)\n if (filePath.includes(`/${stub}/`) || filePath.includes(`/${stub}.rb`)) return true\n return false\n })\n\n if (isStubbed) {\n this.log(`Stubbed module: ${filePath}`)\n return {\n code: '// Stubbed module\\nOpal.loaded([\"' + fileName + '\"]);\\n',\n map: undefined,\n dependencies: []\n }\n }\n\n return null\n }\n\n private recordMetrics(filePath: string, startTime: number, cacheHit: boolean, source: 'memory' | 'disk' | 'compile'): void {\n if (!this.options.metrics) return\n\n const duration = performance.now() - startTime\n this.metrics.push({\n file: path.basename(filePath),\n duration,\n cacheHit,\n source\n })\n }\n\n /**\n * Get compilation metrics summary\n */\n getMetricsSummary(): { total: number; cached: number; compiled: number; avgDuration: number; details: CompileMetrics[] } {\n const total = this.metrics.length\n const cached = this.metrics.filter(m => m.cacheHit).length\n const compiled = total - cached\n const avgDuration = total > 0\n ? this.metrics.reduce((sum, m) => sum + m.duration, 0) / total\n : 0\n\n return {\n total,\n cached,\n compiled,\n avgDuration: Math.round(avgDuration * 100) / 100,\n details: [...this.metrics]\n }\n }\n\n /**\n * Print metrics summary to console\n */\n printMetricsSummary(): void {\n const summary = this.getMetricsSummary()\n console.log('\\n[vite-plugin-opal] Compilation Metrics:')\n console.log(` Total files: ${summary.total}`)\n console.log(` Cache hits: ${summary.cached} (${Math.round(summary.cached / summary.total * 100) || 0}%)`)\n console.log(` Compiled: ${summary.compiled}`)\n console.log(` Avg duration: ${summary.avgDuration}ms`)\n\n if (this.options.debug && summary.details.length > 0) {\n console.log('\\n Details:')\n for (const m of summary.details) {\n console.log(` ${m.file}: ${Math.round(m.duration)}ms (${m.source})`)\n }\n }\n }\n\n /**\n * Clear metrics\n */\n clearMetrics(): void {\n this.metrics = []\n }\n\n async getOpalRuntime(): Promise<string> {\n if (this.runtimeCache) {\n return this.runtimeCache\n }\n\n this.log('Loading Opal runtime')\n const runtime = await this.getRuntimeViaRuby()\n this.runtimeCache = runtime\n return runtime\n }\n\n clearCache(filePath?: string, clearDisk = false): void {\n if (filePath) {\n this.cache.delete(filePath)\n if (clearDisk && this.options.diskCache) {\n try {\n const cachePath = this.getDiskCachePath(filePath)\n if (existsSync(cachePath)) {\n const fsSync = require('fs')\n fsSync.unlinkSync(cachePath)\n }\n } catch (e) {\n this.log(`Failed to clear disk cache for ${filePath}: ${e}`)\n }\n }\n this.log(`Cache cleared: ${filePath}`)\n } else {\n this.cache.clear()\n if (clearDisk && this.options.diskCache) {\n this.clearDiskCache()\n }\n this.log('Cache cleared (all)')\n }\n }\n\n /**\n * Clear all disk cache files\n */\n clearDiskCache(): void {\n if (!this.options.diskCache) return\n\n try {\n const fsSync = require('fs')\n if (existsSync(this.cacheDir)) {\n const files = fsSync.readdirSync(this.cacheDir)\n for (const file of files) {\n if (file.endsWith('.json')) {\n fsSync.unlinkSync(path.join(this.cacheDir, file))\n }\n }\n this.log(`Cleared ${files.length} disk cache files`)\n }\n } catch (e) {\n this.log(`Failed to clear disk cache: ${e}`)\n }\n }\n\n /**\n * Get disk cache statistics\n */\n getDiskCacheStats(): { files: number; size: number } {\n if (!this.options.diskCache || !existsSync(this.cacheDir)) {\n return { files: 0, size: 0 }\n }\n\n try {\n const fsSync = require('fs')\n const files = fsSync.readdirSync(this.cacheDir)\n .filter((f: string) => f.endsWith('.json'))\n let totalSize = 0\n for (const file of files) {\n const stat = fsSync.statSync(path.join(this.cacheDir, file))\n totalSize += stat.size\n }\n return { files: files.length, size: totalSize }\n } catch (e) {\n return { files: 0, size: 0 }\n }\n }\n\n private async compileViaRuby(filePath: string): Promise<CompileResult> {\n return new Promise((resolve, reject) => {\n let command: string\n let args: string[]\n\n if (this.useBundler) {\n command = 'bundle'\n args = [\n 'exec', 'ruby',\n '-r', 'opal-vite',\n '-e', this.getCompilerScript(),\n filePath\n ]\n } else {\n const gemLibPath = this.resolveGemLibPath()\n command = 'ruby'\n args = [\n '-I', gemLibPath,\n '-e', `$LOAD_PATH.unshift('${gemLibPath}'); require 'opal-vite'; ${this.getCompilerScript()}`,\n filePath\n ]\n }\n\n this.log(`Spawning Ruby: ${command} ${args.join(' ')}`)\n\n const ruby = spawn(command, args, {\n cwd: process.cwd()\n })\n\n let stdout = ''\n let stderr = ''\n\n ruby.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n\n ruby.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n\n ruby.on('close', (code) => {\n if (code !== 0) {\n const parsedError = parseRubyError(stderr, filePath)\n const formattedMessage = formatCompilationError(parsedError)\n console.error(formattedMessage)\n\n // Create an error with structured information for Vite\n const error = new Error(parsedError.message) as Error & OpalCompilationError\n error.file = parsedError.file\n error.line = parsedError.line\n error.column = parsedError.column\n error.errorType = parsedError.errorType\n error.hint = parsedError.hint\n error.rawOutput = parsedError.rawOutput\n\n reject(error)\n return\n }\n\n try {\n const result = JSON.parse(stdout)\n resolve(result)\n } catch (e) {\n const parseError = new Error(`Failed to parse compiler output: ${e}`)\n console.error('\\x1b[31m✖ Opal Compiler Output Parse Error\\x1b[0m')\n console.error(` \\x1b[36m→ ${filePath}\\x1b[0m`)\n console.error(` \\x1b[37mUnexpected output from Ruby compiler\\x1b[0m`)\n if (this.options.debug) {\n console.error(` \\x1b[90mRaw output: ${stdout.substring(0, 500)}...\\x1b[0m`)\n }\n reject(parseError)\n }\n })\n\n ruby.on('error', (err) => {\n console.error('\\x1b[31m✖ Ruby Process Error\\x1b[0m')\n console.error(` \\x1b[37m${err.message}\\x1b[0m`)\n console.error(` \\x1b[33m💡 Make sure Ruby and Opal are installed correctly\\x1b[0m`)\n reject(new Error(`Failed to spawn Ruby process: ${err.message}`))\n })\n })\n }\n\n private async getRuntimeViaRuby(): Promise<string> {\n return new Promise((resolve, reject) => {\n let command: string\n let args: string[]\n\n if (this.useBundler) {\n command = 'bundle'\n args = [\n 'exec', 'ruby',\n '-r', 'opal-vite',\n '-e', 'puts Opal::Vite::Compiler.runtime_code'\n ]\n } else {\n const gemLibPath = this.resolveGemLibPath()\n command = 'ruby'\n args = [\n '-I', gemLibPath,\n '-e', `$LOAD_PATH.unshift('${gemLibPath}'); require 'opal-vite'; puts Opal::Vite::Compiler.runtime_code`\n ]\n }\n\n const ruby = spawn(command, args, {\n cwd: process.cwd()\n })\n\n let stdout = ''\n let stderr = ''\n\n ruby.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n\n ruby.stderr.on('data', (data) => {\n stderr += data.toString()\n })\n\n ruby.on('close', (code) => {\n if (code === 0) {\n resolve(stdout)\n } else {\n reject(new Error(`Failed to get Opal runtime:\\n${stderr}`))\n }\n })\n\n ruby.on('error', (err) => {\n reject(new Error(`Failed to spawn Ruby process: ${err.message}`))\n })\n })\n }\n\n private getCompilerScript(): string {\n const includeConcerns = this.options.includeConcerns\n const sourceMap = this.options.sourceMap\n const stubs = JSON.stringify(this.options.stubs)\n // Note: opal-vite is already required via -r flag or -I flag\n // The $LOAD_PATH is set up by -I option, so require 'opal-vite' will find it\n return `\n file_path = ARGV[0]\n stubs = ${stubs}\n Opal::Vite.compile_for_vite(file_path, include_concerns: ${includeConcerns}, source_map: ${sourceMap}, stubs: stubs)\n `.trim()\n }\n\n private resolveGemLibPath(): string {\n // Try to resolve the gem path\n // In development, this points to our local gem\n // In production, bundler will handle it\n if (this.options.gemPath.startsWith('.') || this.options.gemPath.startsWith('/')) {\n return path.resolve(this.options.gemPath, 'lib')\n }\n return this.options.gemPath\n }\n\n private log(message: string): void {\n if (this.options.debug) {\n console.log(`[vite-plugin-opal] ${message}`)\n }\n }\n}\n","import * as path from 'path'\nimport * as fs from 'fs/promises'\nimport type { OpalPluginOptions } from './types'\n\nexport class OpalResolver {\n private options: Required<OpalPluginOptions>\n private loadPaths: string[]\n private resolveCache: Map<string, string | null> = new Map()\n\n constructor(options: OpalPluginOptions = {}) {\n this.options = {\n gemPath: options.gemPath || 'opal-vite',\n sourceMap: options.sourceMap !== false,\n loadPaths: options.loadPaths || ['./src'],\n arityCheck: options.arityCheck || false,\n freezing: options.freezing !== false,\n debug: options.debug || false\n }\n this.loadPaths = this.options.loadPaths\n }\n\n /**\n * Resolve a Ruby file import\n * Supports:\n * - Absolute paths: /path/to/file.rb\n * - Relative paths: ./file.rb, ../file.rb\n * - Load path resolution: file (searches in loadPaths)\n */\n async resolve(id: string, importer?: string): Promise<string | null> {\n // Check cache first\n const cacheKey = `${id}|${importer || ''}`\n if (this.resolveCache.has(cacheKey)) {\n return this.resolveCache.get(cacheKey)!\n }\n\n let resolved: string | null = null\n\n // Only resolve .rb files or files without extension\n if (id.endsWith('.rb') || !this.hasExtension(id)) {\n // Try different resolution strategies\n resolved = await this.resolveAbsolute(id) ||\n await this.resolveRelative(id, importer) ||\n await this.resolveFromLoadPaths(id)\n }\n\n // Cache the result\n this.resolveCache.set(cacheKey, resolved)\n\n if (resolved && this.options.debug) {\n console.log(`[vite-plugin-opal] Resolved: ${id} -> ${resolved}`)\n }\n\n return resolved\n }\n\n /**\n * Clear the resolution cache\n */\n clearCache(filePath?: string): void {\n if (filePath) {\n // Clear cache entries related to this file\n for (const [key, value] of this.resolveCache.entries()) {\n if (value === filePath || key.startsWith(filePath)) {\n this.resolveCache.delete(key)\n }\n }\n } else {\n this.resolveCache.clear()\n }\n }\n\n /**\n * Get all load paths\n */\n getLoadPaths(): string[] {\n return [...this.loadPaths]\n }\n\n /**\n * Add a load path\n */\n addLoadPath(loadPath: string): void {\n if (!this.loadPaths.includes(loadPath)) {\n this.loadPaths.push(loadPath)\n this.clearCache() // Clear cache when load paths change\n }\n }\n\n private async resolveAbsolute(id: string): Promise<string | null> {\n if (!path.isAbsolute(id)) {\n return null\n }\n\n // Try as-is\n if (await this.fileExists(id)) {\n return id\n }\n\n // Try with .rb extension\n if (!id.endsWith('.rb')) {\n const withExt = `${id}.rb`\n if (await this.fileExists(withExt)) {\n return withExt\n }\n }\n\n return null\n }\n\n private async resolveRelative(id: string, importer?: string): Promise<string | null> {\n if (!id.startsWith('.') || !importer) {\n return null\n }\n\n const importerDir = path.dirname(importer)\n const resolved = path.resolve(importerDir, id)\n\n // Try as-is\n if (await this.fileExists(resolved)) {\n return resolved\n }\n\n // Try with .rb extension\n if (!id.endsWith('.rb')) {\n const withExt = `${resolved}.rb`\n if (await this.fileExists(withExt)) {\n return withExt\n }\n }\n\n return null\n }\n\n private async resolveFromLoadPaths(id: string): Promise<string | null> {\n // Remove .rb extension for load path search\n const baseId = id.endsWith('.rb') ? id.slice(0, -3) : id\n\n for (const loadPath of this.loadPaths) {\n // Try with original id\n const fullPath = path.resolve(loadPath, id)\n if (await this.fileExists(fullPath)) {\n return fullPath\n }\n\n // Try with .rb extension\n const withExt = path.resolve(loadPath, `${baseId}.rb`)\n if (await this.fileExists(withExt)) {\n return withExt\n }\n\n // Try as a directory with index.rb\n const indexPath = path.resolve(loadPath, baseId, 'index.rb')\n if (await this.fileExists(indexPath)) {\n return indexPath\n }\n }\n\n return null\n }\n\n private async fileExists(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath)\n return stat.isFile()\n } catch {\n return false\n }\n }\n\n private hasExtension(filePath: string): boolean {\n const ext = path.extname(filePath)\n return ext !== ''\n }\n}\n","import type { ViteDevServer, ModuleNode, Update } from 'vite'\nimport type { OpalCompiler } from './compiler'\nimport type { OpalResolver } from './resolver'\nimport type { OpalPluginOptions } from './types'\nimport * as path from 'path'\nimport * as chokidar from 'chokidar'\n\nexport interface HMRManager {\n setup(): void\n cleanup(): void\n handleFileChange(filePath: string): Promise<void>\n}\n\nexport class OpalHMRManager implements HMRManager {\n private server: ViteDevServer\n private compiler: OpalCompiler\n private resolver: OpalResolver\n private options: OpalPluginOptions\n private watcher?: chokidar.FSWatcher\n private dependencyGraph: Map<string, Set<string>> = new Map()\n\n constructor(\n server: ViteDevServer,\n compiler: OpalCompiler,\n resolver: OpalResolver,\n options: OpalPluginOptions\n ) {\n this.server = server\n this.compiler = compiler\n this.resolver = resolver\n this.options = options\n }\n\n /**\n * Setup HMR file watching\n */\n setup(): void {\n this.log('Setting up HMR for .rb files')\n\n // Watch .rb files for changes\n this.watcher = chokidar.watch('**/*.rb', {\n ignored: /node_modules/,\n persistent: true,\n cwd: this.server.config.root,\n ignoreInitial: true // Don't trigger on initial scan\n })\n\n this.watcher.on('change', async (filePath: string) => {\n await this.handleFileChange(filePath)\n })\n\n this.watcher.on('add', async (filePath: string) => {\n this.log(`New file detected: ${filePath}`)\n await this.handleFileChange(filePath)\n })\n\n this.watcher.on('unlink', (filePath: string) => {\n this.log(`File removed: ${filePath}`)\n const absolutePath = path.resolve(this.server.config.root, filePath)\n this.compiler.clearCache(absolutePath)\n this.resolver.clearCache(absolutePath)\n this.dependencyGraph.delete(absolutePath)\n })\n\n // Cleanup on server close\n this.server.httpServer?.on('close', () => {\n this.cleanup()\n })\n\n this.log('HMR setup complete')\n }\n\n /**\n * Cleanup resources\n */\n cleanup(): void {\n if (this.watcher) {\n this.log('Cleaning up HMR watcher')\n this.watcher.close()\n this.watcher = undefined\n }\n }\n\n /**\n * Handle file change and trigger HMR update\n */\n async handleFileChange(filePath: string): Promise<void> {\n const absolutePath = path.resolve(this.server.config.root, filePath)\n\n this.log(`File changed: ${filePath}`)\n\n try {\n // Clear caches for the changed file\n this.compiler.clearCache(absolutePath)\n this.resolver.clearCache(absolutePath)\n\n // Get the module from the module graph\n const module = this.server.moduleGraph.getModuleById(absolutePath)\n\n if (!module) {\n this.log(`Module not found in graph: ${filePath}`, 'warn')\n return\n }\n\n // Collect all modules that need to be updated\n const modulesToUpdate = new Set<ModuleNode>([module])\n\n // Find dependent modules (modules that import this one)\n await this.collectDependentModules(module, modulesToUpdate)\n\n // Invalidate all affected modules\n for (const mod of modulesToUpdate) {\n this.server.moduleGraph.invalidateModule(mod)\n this.log(`Invalidated: ${mod.url}`)\n }\n\n // Build HMR updates\n const updates: Update[] = Array.from(modulesToUpdate).map(mod => ({\n type: 'js-update' as const,\n path: mod.url,\n acceptedPath: mod.url,\n timestamp: Date.now()\n }))\n\n // Send HMR update to browser\n this.server.ws.send({\n type: 'update',\n updates\n })\n\n this.log(`✓ HMR update sent for ${updates.length} module(s)`, 'success')\n } catch (error) {\n this.handleError(filePath, error)\n }\n }\n\n /**\n * Collect all modules that depend on the given module\n */\n private async collectDependentModules(\n module: ModuleNode,\n result: Set<ModuleNode>\n ): Promise<void> {\n // Get modules that import this module\n for (const importer of module.importers) {\n if (!result.has(importer)) {\n result.add(importer)\n // Recursively collect their dependents\n await this.collectDependentModules(importer, result)\n }\n }\n }\n\n /**\n * Handle compilation or HMR errors\n */\n private handleError(filePath: string, error: unknown): void {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n this.log(`Error processing ${filePath}: ${errorMessage}`, 'error')\n\n // Send error overlay to browser\n this.server.ws.send({\n type: 'error',\n err: {\n message: `Opal compilation failed for ${filePath}`,\n stack: error instanceof Error ? error.stack : undefined,\n id: filePath,\n frame: this.extractErrorFrame(errorMessage),\n plugin: 'vite-plugin-opal',\n loc: this.extractErrorLocation(errorMessage)\n }\n })\n }\n\n /**\n * Extract error frame from error message\n */\n private extractErrorFrame(errorMessage: string): string | undefined {\n // Try to extract relevant code frame from error\n const lines = errorMessage.split('\\n')\n const relevantLines = lines.slice(0, 10).join('\\n')\n return relevantLines || undefined\n }\n\n /**\n * Extract error location from error message\n */\n private extractErrorLocation(errorMessage: string): { file?: string; line?: number; column?: number } | undefined {\n // Try to parse location from Opal error messages\n // Example: \"file.rb:10:5: error message\"\n const match = errorMessage.match(/(.+):(\\d+):(\\d+)/)\n if (match) {\n return {\n file: match[1],\n line: parseInt(match[2], 10),\n column: parseInt(match[3], 10)\n }\n }\n return undefined\n }\n\n /**\n * Log HMR messages\n */\n private log(message: string, level: 'info' | 'warn' | 'error' | 'success' = 'info'): void {\n if (!this.options.debug && level === 'info') {\n return\n }\n\n const prefix = '[vite-plugin-opal:hmr]'\n const timestamp = new Date().toLocaleTimeString()\n\n const colors = {\n info: '\\x1b[36m', // Cyan\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n success: '\\x1b[32m' // Green\n }\n const reset = '\\x1b[0m'\n\n const color = colors[level]\n const levelText = level.toUpperCase().padEnd(7)\n\n console.log(`${color}${prefix} ${timestamp} [${levelText}]${reset} ${message}`)\n }\n\n /**\n * Get dependency graph information (for debugging)\n */\n getDependencyGraph(): Map<string, Set<string>> {\n return new Map(this.dependencyGraph)\n }\n}\n","import type { Plugin, ViteDevServer } from 'vite'\nimport { OpalCompiler } from './compiler'\nimport { OpalResolver } from './resolver'\nimport { OpalHMRManager } from './hmr'\nimport type { OpalPluginOptions } from './types'\nimport * as path from 'path'\n\nconst VIRTUAL_RUNTIME_ID = '/@opal-runtime'\nconst VIRTUAL_RUNTIME_PREFIX = '\\0' + VIRTUAL_RUNTIME_ID\n\n/**\n * Vite plugin for compiling Ruby files to JavaScript using Opal.\n *\n * @param options - Plugin configuration options\n * @returns Vite plugin instance\n *\n * @example\n * ```ts\n * import { defineConfig } from 'vite'\n * import opal from 'vite-plugin-opal'\n *\n * export default defineConfig({\n * plugins: [\n * opal({\n * loadPaths: ['./app/opal'],\n * sourceMap: true\n * })\n * ]\n * })\n * ```\n *\n * @see {@link OpalPluginOptions} for all available options\n */\nexport default function opalPlugin(options: OpalPluginOptions = {}): Plugin {\n const compiler = new OpalCompiler(options)\n const resolver = new OpalResolver(options)\n let server: ViteDevServer | undefined\n let hmrManager: OpalHMRManager | undefined\n let isBuild = false\n\n return {\n name: 'vite-plugin-opal',\n enforce: 'pre', // Run before other plugins\n\n // Detect build vs serve mode\n config(_config, { command }) {\n isBuild = command === 'build'\n },\n\n // Mark .rb files as valid imports\n async resolveId(id: string, importer?: string) {\n // Handle virtual runtime module\n if (id === VIRTUAL_RUNTIME_ID) {\n if (options.debug) {\n console.log(`[vite-plugin-opal] Resolved virtual runtime: ${VIRTUAL_RUNTIME_PREFIX}`)\n }\n return VIRTUAL_RUNTIME_PREFIX\n }\n\n // Handle .rb files and files without extension (Opal style requires)\n if (id.endsWith('.rb') || (!id.includes('.') && !id.startsWith('/'))) {\n const resolved = await resolver.resolve(id, importer)\n if (options.debug) {\n console.log(`[vite-plugin-opal] resolveId: ${id} -> ${resolved}`)\n }\n return resolved\n }\n\n return null\n },\n\n // Load and compile .rb files\n async load(id: string) {\n // Handle virtual runtime module\n if (id === VIRTUAL_RUNTIME_PREFIX) {\n if (options.debug) {\n console.log(`[vite-plugin-opal] Loading Opal runtime...`)\n }\n const runtime = await compiler.getOpalRuntime()\n if (options.debug) {\n console.log(`[vite-plugin-opal] Opal runtime loaded: ${runtime.length} bytes`)\n }\n return {\n code: runtime,\n map: null\n }\n }\n\n // Handle .rb files\n if (id.endsWith('.rb')) {\n if (options.debug) {\n console.log(`[vite-plugin-opal] load: Compiling ${id}`)\n }\n try {\n const result = await compiler.compile(id)\n if (options.debug) {\n console.log(`[vite-plugin-opal] load: Compiled ${id} -> ${result.code.length} bytes`)\n console.log(`[vite-plugin-opal] load: Source map: ${result.map ? 'yes' : 'no'}`)\n }\n const sourceMap = result.map ? JSON.parse(result.map) : null\n if (options.debug && sourceMap) {\n console.log(`[vite-plugin-opal] load: Source map version: ${sourceMap.version}, sections: ${sourceMap.sections?.length || 0}`)\n }\n return {\n code: result.code,\n map: sourceMap\n }\n } catch (error) {\n console.error(`[vite-plugin-opal] Compilation error for ${id}:`, error)\n this.error(error instanceof Error ? error.message : String(error))\n }\n }\n\n return null\n },\n\n // Auto-inject Opal runtime into HTML (development only)\n transformIndexHtml(html: string) {\n // Skip injection during build - runtime is bundled into JS\n if (isBuild) {\n return html\n }\n\n // Inject runtime before closing </head> tag (development only)\n const runtimeScript = `<script type=\"module\" src=\"${VIRTUAL_RUNTIME_ID}\"></script>`\n\n if (html.includes('</head>')) {\n return html.replace('</head>', ` ${runtimeScript}\\n</head>`)\n } else if (html.includes('<head>')) {\n return html.replace('<head>', `<head>\\n ${runtimeScript}`)\n } else {\n // No head tag, inject at the beginning\n return `${runtimeScript}\\n${html}`\n }\n },\n\n // Setup HMR for .rb files\n configureServer(_server: ViteDevServer) {\n server = _server\n\n // Initialize HMR manager\n hmrManager = new OpalHMRManager(server, compiler, resolver, options)\n hmrManager.setup()\n\n return () => {\n // Cleanup function called when server closes\n if (hmrManager) {\n hmrManager.cleanup()\n }\n }\n },\n\n // Print metrics after build completes\n closeBundle() {\n if (options.metrics) {\n compiler.printMetricsSummary()\n }\n }\n }\n}\n\nexport type { OpalPluginOptions } from './types'\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-opal",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Vite plugin for Opal - Compile Ruby to JavaScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",