vite-plugin-opal 0.1.0 → 0.2.0

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
@@ -1,38 +1,165 @@
1
1
  import { Plugin } from 'vite';
2
2
 
3
+ /**
4
+ * Configuration options for the Opal Vite plugin
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { defineConfig } from 'vite'
9
+ * import opal from 'vite-plugin-opal'
10
+ *
11
+ * export default defineConfig({
12
+ * plugins: [
13
+ * opal({
14
+ * loadPaths: ['./app/opal', './lib/opal'],
15
+ * sourceMap: true,
16
+ * debug: false
17
+ * })
18
+ * ]
19
+ * })
20
+ * ```
21
+ */
3
22
  interface OpalPluginOptions {
4
23
  /**
5
- * Path to the opal-vite gem
24
+ * Path to the opal-vite gem directory.
25
+ * If not specified, the gem will be loaded from the default gem path.
26
+ *
6
27
  * @default 'opal-vite'
28
+ * @example
29
+ * ```ts
30
+ * {
31
+ * gemPath: '/path/to/custom/opal-vite'
32
+ * }
33
+ * ```
7
34
  */
8
35
  gemPath?: string;
9
36
  /**
10
- * Enable source map generation
37
+ * Enable source map generation for debugging Ruby code in browser DevTools.
38
+ * When enabled, you can set breakpoints and step through your Ruby code.
39
+ *
11
40
  * @default true
41
+ * @example
42
+ * ```ts
43
+ * {
44
+ * sourceMap: true // Enable for development
45
+ * }
46
+ * ```
12
47
  */
13
48
  sourceMap?: boolean;
14
49
  /**
15
- * Load paths for Ruby requires
50
+ * Additional load paths for Ruby `require` statements.
51
+ * Files in these directories can be required without specifying the full path.
52
+ *
16
53
  * @default ['./src']
54
+ * @example
55
+ * ```ts
56
+ * {
57
+ * loadPaths: [
58
+ * './app/opal', // Application code
59
+ * './lib/opal', // Libraries
60
+ * './app/controllers' // Controllers
61
+ * ]
62
+ * }
63
+ * ```
17
64
  */
18
65
  loadPaths?: string[];
19
66
  /**
20
- * Enable arity checking
67
+ * Enable runtime arity checking for method calls.
68
+ * When enabled, Opal will check that methods are called with the correct number of arguments.
69
+ * Useful for development, but adds runtime overhead.
70
+ *
21
71
  * @default false
72
+ * @example
73
+ * ```ts
74
+ * {
75
+ * arityCheck: true // Enable for development
76
+ * }
77
+ * ```
22
78
  */
23
79
  arityCheck?: boolean;
24
80
  /**
25
- * Enable object freezing
81
+ * Enable object freezing to prevent modification of frozen objects.
82
+ * This matches Ruby's Object#freeze behavior more closely.
83
+ *
26
84
  * @default true
85
+ * @example
86
+ * ```ts
87
+ * {
88
+ * freezing: true // Enable for Ruby compliance
89
+ * }
90
+ * ```
27
91
  */
28
92
  freezing?: boolean;
29
93
  /**
30
- * Enable debug logging
94
+ * Enable debug logging to console.
95
+ * Logs compilation steps, file resolutions, and HMR updates.
96
+ * Useful for troubleshooting compilation issues.
97
+ *
31
98
  * @default false
99
+ * @example
100
+ * ```ts
101
+ * {
102
+ * debug: true // Enable to see plugin activity
103
+ * }
104
+ * ```
32
105
  */
33
106
  debug?: boolean;
107
+ /**
108
+ * Use `bundle exec` to run Ruby commands.
109
+ * Automatically detects presence of Gemfile if not specified.
110
+ * Set to `false` to disable bundler even when Gemfile exists.
111
+ *
112
+ * @default auto-detect (true if Gemfile exists in project root)
113
+ * @example
114
+ * ```ts
115
+ * {
116
+ * useBundler: true // Force bundler usage
117
+ * }
118
+ * ```
119
+ */
120
+ useBundler?: boolean;
121
+ /**
122
+ * Include built-in concerns (JsProxyEx, DomHelpers, Toastable, Storable).
123
+ * When enabled, these modules are automatically available via:
124
+ * - `require 'opal_vite/concerns/js_proxy_ex'`
125
+ * - `require 'opal_vite/concerns/dom_helpers'`
126
+ * - `require 'opal_vite/concerns/toastable'`
127
+ * - `require 'opal_vite/concerns/storable'`
128
+ *
129
+ * @default true
130
+ * @example
131
+ * ```ts
132
+ * {
133
+ * includeConcerns: true // Enable built-in concerns
134
+ * }
135
+ * ```
136
+ */
137
+ includeConcerns?: boolean;
34
138
  }
35
139
 
140
+ /**
141
+ * Vite plugin for compiling Ruby files to JavaScript using Opal.
142
+ *
143
+ * @param options - Plugin configuration options
144
+ * @returns Vite plugin instance
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * import { defineConfig } from 'vite'
149
+ * import opal from 'vite-plugin-opal'
150
+ *
151
+ * export default defineConfig({
152
+ * plugins: [
153
+ * opal({
154
+ * loadPaths: ['./app/opal'],
155
+ * sourceMap: true
156
+ * })
157
+ * ]
158
+ * })
159
+ * ```
160
+ *
161
+ * @see {@link OpalPluginOptions} for all available options
162
+ */
36
163
  declare function opalPlugin(options?: OpalPluginOptions): Plugin;
37
164
 
38
165
  export { type OpalPluginOptions, opalPlugin as default };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { spawn } from 'child_process';
2
2
  import * as fs from 'fs/promises';
3
+ import { accessSync } from 'fs';
3
4
  import * as path2 from 'path';
4
5
  import * as chokidar from 'chokidar';
5
6
 
@@ -14,8 +15,25 @@ var OpalCompiler = class {
14
15
  loadPaths: options.loadPaths || ["./src"],
15
16
  arityCheck: options.arityCheck || false,
16
17
  freezing: options.freezing !== false,
17
- debug: options.debug || false
18
+ debug: options.debug || false,
19
+ useBundler: options.useBundler !== void 0 ? options.useBundler : this.detectGemfile(),
20
+ includeConcerns: options.includeConcerns !== false
18
21
  };
22
+ this.useBundler = this.options.useBundler;
23
+ if (this.options.debug) {
24
+ console.log(`[vite-plugin-opal] Using bundler: ${this.useBundler}`);
25
+ console.log(`[vite-plugin-opal] Working directory: ${process.cwd()}`);
26
+ console.log(`[vite-plugin-opal] Include concerns: ${this.options.includeConcerns}`);
27
+ }
28
+ }
29
+ detectGemfile() {
30
+ try {
31
+ const gemfilePath = path2.join(process.cwd(), "Gemfile");
32
+ accessSync(gemfilePath);
33
+ return true;
34
+ } catch {
35
+ return false;
36
+ }
19
37
  }
20
38
  async compile(filePath) {
21
39
  const cached = this.cache.get(filePath);
@@ -66,17 +84,35 @@ var OpalCompiler = class {
66
84
  }
67
85
  async compileViaRuby(filePath) {
68
86
  return new Promise((resolve4, reject) => {
69
- const args = [
70
- "-I",
71
- this.resolveGemLibPath(),
72
- "-r",
73
- "opal-vite",
74
- "-e",
75
- this.getCompilerScript(),
76
- filePath
77
- ];
78
- this.log(`Spawning Ruby: ruby ${args.join(" ")}`);
79
- const ruby = spawn("ruby", args);
87
+ let command;
88
+ let args;
89
+ if (this.useBundler) {
90
+ command = "bundle";
91
+ args = [
92
+ "exec",
93
+ "ruby",
94
+ "-r",
95
+ "opal-vite",
96
+ "-e",
97
+ this.getCompilerScript(),
98
+ filePath
99
+ ];
100
+ } else {
101
+ command = "ruby";
102
+ args = [
103
+ "-I",
104
+ this.resolveGemLibPath(),
105
+ "-r",
106
+ "opal-vite",
107
+ "-e",
108
+ this.getCompilerScript(),
109
+ filePath
110
+ ];
111
+ }
112
+ this.log(`Spawning Ruby: ${command} ${args.join(" ")}`);
113
+ const ruby = spawn(command, args, {
114
+ cwd: process.cwd()
115
+ });
80
116
  let stdout = "";
81
117
  let stderr = "";
82
118
  ruby.stdout.on("data", (data) => {
@@ -108,15 +144,32 @@ Error: ${e}`));
108
144
  }
109
145
  async getRuntimeViaRuby() {
110
146
  return new Promise((resolve4, reject) => {
111
- const args = [
112
- "-I",
113
- this.resolveGemLibPath(),
114
- "-r",
115
- "opal-vite",
116
- "-e",
117
- "puts Opal::Vite::Compiler.runtime_code"
118
- ];
119
- const ruby = spawn("ruby", args);
147
+ let command;
148
+ let args;
149
+ if (this.useBundler) {
150
+ command = "bundle";
151
+ args = [
152
+ "exec",
153
+ "ruby",
154
+ "-r",
155
+ "opal-vite",
156
+ "-e",
157
+ "puts Opal::Vite::Compiler.runtime_code"
158
+ ];
159
+ } else {
160
+ command = "ruby";
161
+ args = [
162
+ "-I",
163
+ this.resolveGemLibPath(),
164
+ "-r",
165
+ "opal-vite",
166
+ "-e",
167
+ "puts Opal::Vite::Compiler.runtime_code"
168
+ ];
169
+ }
170
+ const ruby = spawn(command, args, {
171
+ cwd: process.cwd()
172
+ });
120
173
  let stdout = "";
121
174
  let stderr = "";
122
175
  ruby.stdout.on("data", (data) => {
@@ -139,10 +192,11 @@ ${stderr}`));
139
192
  });
140
193
  }
141
194
  getCompilerScript() {
195
+ const includeConcerns = this.options.includeConcerns;
142
196
  return `
143
197
  require 'opal-vite'
144
198
  file_path = ARGV[0]
145
- Opal::Vite.compile_for_vite(file_path)
199
+ Opal::Vite.compile_for_vite(file_path, include_concerns: ${includeConcerns})
146
200
  `.trim();
147
201
  }
148
202
  resolveGemLibPath() {
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":["stat","resolve","path","fs2","path3"],"mappings":"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","file":"index.js","sourcesContent":["import { spawn } from 'child_process'\nimport * as fs from 'fs/promises'\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\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 }\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 const args = [\n '-I', this.resolveGemLibPath(),\n '-r', 'opal-vite',\n '-e', this.getCompilerScript(),\n filePath\n ]\n\n this.log(`Spawning Ruby: ruby ${args.join(' ')}`)\n\n const ruby = spawn('ruby', args)\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 const args = [\n '-I', this.resolveGemLibPath(),\n '-r', 'opal-vite',\n '-e', 'puts Opal::Vite::Compiler.runtime_code'\n ]\n\n const ruby = spawn('ruby', args)\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 return `\n require 'opal-vite'\n file_path = ARGV[0]\n Opal::Vite.compile_for_vite(file_path)\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\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\n return {\n name: 'vite-plugin-opal',\n enforce: 'pre', // Run before other plugins\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 }\n return {\n code: result.code,\n map: result.map ? JSON.parse(result.map) : null\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\n transformIndexHtml(html: string) {\n // Inject runtime before closing </head> tag\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":["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 return `\n require 'opal-vite'\n file_path = ARGV[0]\n Opal::Vite.compile_for_vite(file_path, include_concerns: ${includeConcerns})\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\n return {\n name: 'vite-plugin-opal',\n enforce: 'pre', // Run before other plugins\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 }\n return {\n code: result.code,\n map: result.map ? JSON.parse(result.map) : null\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\n transformIndexHtml(html: string) {\n // Inject runtime before closing </head> tag\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-opal",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Vite plugin for Opal - Compile Ruby to JavaScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",