@react-synth/synth 0.1.0-alpha ā 0.2.1-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +361 -361
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +80 -80
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","sources":["../cli/cli.ts"],"sourcesContent":["#!/usr/bin/env node\
|
|
1
|
+
{"version":3,"file":"cli.cjs","sources":["../cli/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { resolve } from \"path\";\nimport {\n createServer,\n type ModuleNode,\n normalizePath,\n type ViteDevServer,\n} from \"vite\";\nimport { JSDOM } from \"jsdom\";\nimport { type ComponentType, createElement } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\n// Create fake DOM for React\nconst dom = new JSDOM('<!DOCTYPE html><div id=\"root\"></div>');\n\n// Polyfill globals that React needs\n(globalThis as any).document = dom.window.document;\n(globalThis as any).window = dom.window;\n\nlet root: Root | null = null;\n\nfunction renderSong(SongComponent: ComponentType): void {\n const container = document.getElementById(\"root\")!;\n\n if (!root) {\n root = createRoot(container);\n }\n\n root.render(createElement(SongComponent));\n}\n\nasync function main(): Promise<void> {\n const filePath = process.argv[2];\n\n if (!filePath) {\n console.log(`\nš¹ React Synth - Live coding music with React\n\nUsage: \n npx react-synth <song.tsx> Run a song with hot reload\n`);\n process.exit(0);\n }\n\n // Use normalizePath for consistent forward slashes (Vite uses forward slashes internally)\n const absolutePath = normalizePath(resolve(process.cwd(), filePath));\n console.log(`šµ Loading ${filePath}...`);\n\n const vite: ViteDevServer = await createServer({\n configFile: false,\n root: process.cwd(),\n server: {\n middlewareMode: true,\n hmr: true,\n },\n appType: \"custom\",\n optimizeDeps: {\n exclude: [\"@react-synth/synth\", \"node-web-audio-api\"],\n },\n ssr: {\n external: [\"node-web-audio-api\", \"jsdom\"],\n noExternal: [\"@react-synth/synth\", \"tonal\"],\n },\n esbuild: {\n jsx: \"automatic\",\n },\n logLevel: \"info\",\n });\n\n let currentModuleUrl: string | null = null;\n\n async function loadSong(): Promise<void> {\n const url = `${absolutePath}?t=${Date.now()}`;\n\n // Invalidate the previous module if it exists\n if (currentModuleUrl) {\n const mod = await vite.moduleGraph.getModuleByUrl(currentModuleUrl);\n if (mod) {\n invalidateModuleAndImporters(mod);\n }\n }\n\n currentModuleUrl = url;\n const module = await vite.ssrLoadModule(url);\n\n // Auto-render the default export if it's a component\n if (module.default && typeof module.default === \"function\") {\n renderSong(module.default);\n } else {\n console.warn(\n \"ā ļø No default export found. Song file should export a React component as default.\",\n );\n }\n }\n\n // Recursively invalidate a module and all its importers\n function invalidateModuleAndImporters(mod: ModuleNode): void {\n vite.moduleGraph.invalidateModule(mod);\n for (const importer of mod.importers) {\n invalidateModuleAndImporters(importer);\n }\n }\n\n // Collect all dependencies (imports) of a module recursively\n function collectDependencies(\n mod: ModuleNode,\n visited: Set<string> = new Set(),\n ): Set<string> {\n if (mod.file) {\n visited.add(mod.file);\n }\n\n for (const imported of mod.ssrImportedModules) {\n if (imported.file && !visited.has(imported.file)) {\n collectDependencies(imported, visited);\n }\n }\n\n return visited;\n }\n\n // Check if a file is a dependency of the song module\n function isDependencyOfSong(changedFile: string): boolean {\n const songMod = vite.moduleGraph.getModulesByFile(absolutePath);\n if (!songMod || songMod.size === 0) {\n return false;\n }\n\n for (const mod of songMod) {\n const deps = collectDependencies(mod);\n if (deps.has(changedFile)) {\n return true;\n }\n }\n\n return false;\n }\n\n await loadSong();\n console.log(\"š¹ Playing track\");\n console.log(\" Watching for changes...\");\n\n let debounce: ReturnType<typeof setTimeout> | undefined;\n\n vite.watcher.on(\"change\", async (changedPath) => {\n // Normalize to forward slashes to match Vite's module graph\n const normalizedChanged = normalizePath(resolve(changedPath));\n\n // Reload if the song file itself changed, or any of its dependencies\n if (!isDependencyOfSong(normalizedChanged)) {\n return;\n }\n\n clearTimeout(debounce);\n debounce = setTimeout(async () => {\n try {\n await loadSong();\n console.log(`ā
Hot reloaded (${changedPath})`);\n } catch (e) {\n console.error(\"ā Error:\", e instanceof Error ? e.message : String(e));\n }\n }, 50);\n });\n\n process.on(\"SIGINT\", async () => {\n console.log(\"\\nš Stopping...\");\n await vite.close();\n process.exit(0);\n });\n}\n\nmain().catch(console.error);\n"],"names":["JSDOM","createRoot","createElement","normalizePath","resolve","vite","createServer","module"],"mappings":";;;;;;;AAaA,MAAM,MAAM,IAAIA,MAAAA,MAAM,sCAAsC;AAG3D,WAAmB,WAAW,IAAI,OAAO;AACzC,WAAmB,SAAS,IAAI;AAEjC,IAAI,OAAoB;AAExB,SAAS,WAAW,eAAoC;AACtD,QAAM,YAAY,SAAS,eAAe,MAAM;AAEhD,MAAI,CAAC,MAAM;AACT,WAAOC,OAAAA,WAAW,SAAS;AAAA,EAC7B;AAEA,OAAK,OAAOC,oBAAc,aAAa,CAAC;AAC1C;AAEA,eAAe,OAAsB;AACnC,QAAM,WAAW,QAAQ,KAAK,CAAC;AAE/B,MAAI,CAAC,UAAU;AACb,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,CAKf;AACG,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,eAAeC,KAAAA,cAAcC,KAAAA,QAAQ,QAAQ,IAAA,GAAO,QAAQ,CAAC;AACnE,UAAQ,IAAI,cAAc,QAAQ,KAAK;AAEvC,QAAMC,SAAsB,MAAMC,kBAAa;AAAA,IAC7C,YAAY;AAAA,IACZ,MAAM,QAAQ,IAAA;AAAA,IACd,QAAQ;AAAA,MACN,gBAAgB;AAAA,MAChB,KAAK;AAAA,IAAA;AAAA,IAEP,SAAS;AAAA,IACT,cAAc;AAAA,MACZ,SAAS,CAAC,sBAAsB,oBAAoB;AAAA,IAAA;AAAA,IAEtD,KAAK;AAAA,MACH,UAAU,CAAC,sBAAsB,OAAO;AAAA,MACxC,YAAY,CAAC,sBAAsB,OAAO;AAAA,IAAA;AAAA,IAE5C,SAAS;AAAA,MACP,KAAK;AAAA,IAAA;AAAA,IAEP,UAAU;AAAA,EAAA,CACX;AAED,MAAI,mBAAkC;AAEtC,iBAAe,WAA0B;AACvC,UAAM,MAAM,GAAG,YAAY,MAAM,KAAK,KAAK;AAG3C,QAAI,kBAAkB;AACpB,YAAM,MAAM,MAAMD,OAAK,YAAY,eAAe,gBAAgB;AAClE,UAAI,KAAK;AACP,qCAA6B,GAAG;AAAA,MAClC;AAAA,IACF;AAEA,uBAAmB;AACnB,UAAME,UAAS,MAAMF,OAAK,cAAc,GAAG;AAG3C,QAAIE,QAAO,WAAW,OAAOA,QAAO,YAAY,YAAY;AAC1D,iBAAWA,QAAO,OAAO;AAAA,IAC3B,OAAO;AACL,cAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAGA,WAAS,6BAA6B,KAAuB;AAC3DF,WAAK,YAAY,iBAAiB,GAAG;AACrC,eAAW,YAAY,IAAI,WAAW;AACpC,mCAA6B,QAAQ;AAAA,IACvC;AAAA,EACF;AAGA,WAAS,oBACP,KACA,UAAuB,oBAAI,OACd;AACb,QAAI,IAAI,MAAM;AACZ,cAAQ,IAAI,IAAI,IAAI;AAAA,IACtB;AAEA,eAAW,YAAY,IAAI,oBAAoB;AAC7C,UAAI,SAAS,QAAQ,CAAC,QAAQ,IAAI,SAAS,IAAI,GAAG;AAChD,4BAAoB,UAAU,OAAO;AAAA,MACvC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAGA,WAAS,mBAAmB,aAA8B;AACxD,UAAM,UAAUA,OAAK,YAAY,iBAAiB,YAAY;AAC9D,QAAI,CAAC,WAAW,QAAQ,SAAS,GAAG;AAClC,aAAO;AAAA,IACT;AAEA,eAAW,OAAO,SAAS;AACzB,YAAM,OAAO,oBAAoB,GAAG;AACpC,UAAI,KAAK,IAAI,WAAW,GAAG;AACzB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,SAAA;AACN,UAAQ,IAAI,kBAAkB;AAC9B,UAAQ,IAAI,4BAA4B;AAExC,MAAI;AAEJA,SAAK,QAAQ,GAAG,UAAU,OAAO,gBAAgB;AAE/C,UAAM,oBAAoBF,KAAAA,cAAcC,KAAAA,QAAQ,WAAW,CAAC;AAG5D,QAAI,CAAC,mBAAmB,iBAAiB,GAAG;AAC1C;AAAA,IACF;AAEA,iBAAa,QAAQ;AACrB,eAAW,WAAW,YAAY;AAChC,UAAI;AACF,cAAM,SAAA;AACN,gBAAQ,IAAI,mBAAmB,WAAW,GAAG;AAAA,MAC/C,SAAS,GAAG;AACV,gBAAQ,MAAM,YAAY,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,MACtE;AAAA,IACF,GAAG,EAAE;AAAA,EACP,CAAC;AAED,UAAQ,GAAG,UAAU,YAAY;AAC/B,YAAQ,IAAI,kBAAkB;AAC9B,UAAMC,OAAK,MAAA;AACX,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;AAEA,OAAO,MAAM,QAAQ,KAAK;"}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../cli/cli.ts"],"sourcesContent":["#!/usr/bin/env node\
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../cli/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { resolve } from \"path\";\nimport {\n createServer,\n type ModuleNode,\n normalizePath,\n type ViteDevServer,\n} from \"vite\";\nimport { JSDOM } from \"jsdom\";\nimport { type ComponentType, createElement } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\n// Create fake DOM for React\nconst dom = new JSDOM('<!DOCTYPE html><div id=\"root\"></div>');\n\n// Polyfill globals that React needs\n(globalThis as any).document = dom.window.document;\n(globalThis as any).window = dom.window;\n\nlet root: Root | null = null;\n\nfunction renderSong(SongComponent: ComponentType): void {\n const container = document.getElementById(\"root\")!;\n\n if (!root) {\n root = createRoot(container);\n }\n\n root.render(createElement(SongComponent));\n}\n\nasync function main(): Promise<void> {\n const filePath = process.argv[2];\n\n if (!filePath) {\n console.log(`\nš¹ React Synth - Live coding music with React\n\nUsage: \n npx react-synth <song.tsx> Run a song with hot reload\n`);\n process.exit(0);\n }\n\n // Use normalizePath for consistent forward slashes (Vite uses forward slashes internally)\n const absolutePath = normalizePath(resolve(process.cwd(), filePath));\n console.log(`šµ Loading ${filePath}...`);\n\n const vite: ViteDevServer = await createServer({\n configFile: false,\n root: process.cwd(),\n server: {\n middlewareMode: true,\n hmr: true,\n },\n appType: \"custom\",\n optimizeDeps: {\n exclude: [\"@react-synth/synth\", \"node-web-audio-api\"],\n },\n ssr: {\n external: [\"node-web-audio-api\", \"jsdom\"],\n noExternal: [\"@react-synth/synth\", \"tonal\"],\n },\n esbuild: {\n jsx: \"automatic\",\n },\n logLevel: \"info\",\n });\n\n let currentModuleUrl: string | null = null;\n\n async function loadSong(): Promise<void> {\n const url = `${absolutePath}?t=${Date.now()}`;\n\n // Invalidate the previous module if it exists\n if (currentModuleUrl) {\n const mod = await vite.moduleGraph.getModuleByUrl(currentModuleUrl);\n if (mod) {\n invalidateModuleAndImporters(mod);\n }\n }\n\n currentModuleUrl = url;\n const module = await vite.ssrLoadModule(url);\n\n // Auto-render the default export if it's a component\n if (module.default && typeof module.default === \"function\") {\n renderSong(module.default);\n } else {\n console.warn(\n \"ā ļø No default export found. Song file should export a React component as default.\",\n );\n }\n }\n\n // Recursively invalidate a module and all its importers\n function invalidateModuleAndImporters(mod: ModuleNode): void {\n vite.moduleGraph.invalidateModule(mod);\n for (const importer of mod.importers) {\n invalidateModuleAndImporters(importer);\n }\n }\n\n // Collect all dependencies (imports) of a module recursively\n function collectDependencies(\n mod: ModuleNode,\n visited: Set<string> = new Set(),\n ): Set<string> {\n if (mod.file) {\n visited.add(mod.file);\n }\n\n for (const imported of mod.ssrImportedModules) {\n if (imported.file && !visited.has(imported.file)) {\n collectDependencies(imported, visited);\n }\n }\n\n return visited;\n }\n\n // Check if a file is a dependency of the song module\n function isDependencyOfSong(changedFile: string): boolean {\n const songMod = vite.moduleGraph.getModulesByFile(absolutePath);\n if (!songMod || songMod.size === 0) {\n return false;\n }\n\n for (const mod of songMod) {\n const deps = collectDependencies(mod);\n if (deps.has(changedFile)) {\n return true;\n }\n }\n\n return false;\n }\n\n await loadSong();\n console.log(\"š¹ Playing track\");\n console.log(\" Watching for changes...\");\n\n let debounce: ReturnType<typeof setTimeout> | undefined;\n\n vite.watcher.on(\"change\", async (changedPath) => {\n // Normalize to forward slashes to match Vite's module graph\n const normalizedChanged = normalizePath(resolve(changedPath));\n\n // Reload if the song file itself changed, or any of its dependencies\n if (!isDependencyOfSong(normalizedChanged)) {\n return;\n }\n\n clearTimeout(debounce);\n debounce = setTimeout(async () => {\n try {\n await loadSong();\n console.log(`ā
Hot reloaded (${changedPath})`);\n } catch (e) {\n console.error(\"ā Error:\", e instanceof Error ? e.message : String(e));\n }\n }, 50);\n });\n\n process.on(\"SIGINT\", async () => {\n console.log(\"\\nš Stopping...\");\n await vite.close();\n process.exit(0);\n });\n}\n\nmain().catch(console.error);\n"],"names":[],"mappings":"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"}
|