@puzzmo/sdk 1.0.26 → 1.0.28

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/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=require(`./asyncToGenerator-BlxRHn40.cjs`),l=require(`./objectSpread2-B6tAAMuy.cjs`);let u=require(`vite`),d=require(`path`);d=s(d);let f=require(`fs`);f=s(f);function p(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}function m(e,t){if(e==null)return{};var n,r,i=p(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var h=[`fixturesGlob`],g=`/@puzzmo-simulator-init.js`,_=`virtual:puzzmo-simulator`;function v(e){let t=new Map,n=D(e,3);f.default.existsSync(d.default.join(e,`puzzmo.json`))&&n.unshift(e);for(let i of n)try{var r;let n=JSON.parse(f.default.readFileSync(d.default.join(i,`puzzmo.json`),`utf-8`));if(!(!(n==null||(r=n.game)==null)&&r.slug))continue;let a=w(i,`src/appBundle`),o=null;a&&(o=`/`+d.default.relative(e,a).split(d.default.sep).join(`/`)),t.set(n.game.slug,{dir:i,slug:n.game.slug,displayName:n.game.displayName,appBundlePath:o})}catch(e){}return t}function y(e,t,n){if(e)try{let r=new URL(e).pathname;for(let e of t.values()){let t=`/`+d.default.relative(n,e.dir).split(d.default.sep).join(`/`);if(r.startsWith(t+`/`)||r===t)return e}}catch(e){}if(t.size===1)return t.values().next().value}function b(e,t){let{fixturesGlob:n}=e,r=m(e,h),i=n===!1?null:n==null?`/fixtures/puzzles/**/*.json`:n,a=[`import { createSimulator } from "@puzzmo/sdk/simulator"`];i&&a.push(`const fixtures = import.meta.glob(${JSON.stringify(i)}, { eager: true })`),t!=null&&t.appBundlePath&&(a.push(`import(${JSON.stringify(t.appBundlePath)}).then(m => {`),a.push(` if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail`),a.push(`}).catch(() => {})`));let o=l.t(l.t({},r),t!=null&&t.slug?{slug:t.slug}:{}),s=Object.entries(o).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}: ${JSON.stringify(t)}`);return i&&s.push(`fixtures`),a.push(`createSimulator({ ${s.join(`, `)} })`),a.join(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=require(`./asyncToGenerator-BlxRHn40.cjs`),l=require(`./objectSpread2-B6tAAMuy.cjs`);let u=require(`vite`),d=require(`path`);d=s(d);let f=require(`fs`);f=s(f);function p(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}function m(e,t){if(e==null)return{};var n,r,i=p(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var h=[`fixturesGlob`],g=`/@puzzmo-simulator-init.js`,_=`virtual:puzzmo-simulator`;function v(e){let t=new Map,n=D(e,3);f.default.existsSync(d.default.join(e,`puzzmo.json`))&&n.unshift(e);for(let i of n)try{var r;let n=JSON.parse(f.default.readFileSync(d.default.join(i,`puzzmo.json`),`utf-8`));if(!(!(n==null||(r=n.game)==null)&&r.slug))continue;let a=w(i,`src/appBundle`),o=null;a&&(o=`/`+d.default.relative(e,a).split(d.default.sep).join(`/`)),t.set(n.game.slug,{dir:i,slug:n.game.slug,displayName:n.game.displayName,appBundlePath:o})}catch(e){}return t}function y(e,t,n){if(e)try{let r=new URL(e).pathname;for(let e of t.values()){let t=`/`+d.default.relative(n,e.dir).split(d.default.sep).join(`/`);if(r.startsWith(t+`/`)||r===t)return e}}catch(e){}if(t.size===1)return t.values().next().value}function b(e,t){let{fixturesGlob:n}=e,r=m(e,h),i=n===!1?null:n==null?`/fixtures/puzzles/**/*.{json,toml}`:n,a=[`import { createSimulator } from "@puzzmo/sdk/simulator"`];i&&a.push(`const fixtures = import.meta.glob(${JSON.stringify(i)}, { query: "?raw", import: "default", eager: true })`),t!=null&&t.appBundlePath&&(a.push(`import(${JSON.stringify(t.appBundlePath)}).then(m => {`),a.push(` if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail`),a.push(`}).catch(() => {})`));let o=l.t(l.t({},r),t!=null&&t.slug?{slug:t.slug}:{}),s=Object.entries(o).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}: ${JSON.stringify(t)}`);return i&&s.push(`fixtures`),a.push(`createSimulator({ ${s.join(`, `)} })`),a.join(`
2
2
  `)}function x(e={}){let t=new Map,n;return{name:`puzzmo-simulator`,apply:`serve`,configResolved(e){if(n=e.root,t=v(n),t.size===0)e.logger.info(`\x1B[33m\x1B[1m PUZZMO \x1B[22m\x1B[39m\x1B[2m no puzzmo.json files found\x1B[22m`);else{let n=[...t.values()].map(e=>`\x1b[36m${e.slug}\x1b[39m`),r=t.size===1?`game`:`games`;e.logger.info(`\x1b[33m\x1b[1m PUZZMO \x1b[22m\x1b[39m found ${t.size} ${r}: ${n.join(`\x1B[2m, \x1B[22m`)}`)}},resolveId(e){if(e===_||e.startsWith(_+`?`))return`\0`+e},load(n){if(!n.startsWith(`\0`+_))return;let r=new URLSearchParams(n.split(`?`)[1]||``).get(`game`);return b(e,r?t.get(r):t.size===1?t.values().next().value:void 0)},configureServer(e){e.middlewares.use(`/oauth/callback`,(e,t)=>{t.setHeader(`Content-Type`,`text/html`),t.end(`<!DOCTYPE html>
3
3
  <html><head><title>Puzzmo OAuth</title></head>
4
4
  <body><script>
package/dist/vite.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vite.cjs","names":[],"sources":["../src/vite.ts"],"sourcesContent":["import type { Plugin, ResolvedConfig } from \"vite\"\nimport { build } from \"vite\"\nimport path from \"path\"\nimport fs from \"fs\"\n\nexport type PuzzmoSimulatorPluginOptions = {\n /** Whether to auto-start the game after READY (default: true) */\n autoStart?: boolean\n /** Initial collapsed state (default: true) */\n collapsed?: boolean\n /**\n * Glob pattern for fixture files, passed to import.meta.glob which is relative to the closest puzzmo.json. Defaults to\n * `\"/fixtures/puzzles/**\\/*.json\"`. Pass false to disable.\n */\n fixturesGlob?: string | false\n}\n\nconst simulatorURL = \"/@puzzmo-simulator-init.js\"\nconst virtualID = \"virtual:puzzmo-simulator\"\n\n/** @internal */\nexport type GameInfo = {\n /** Directory containing the puzzmo.json */\n dir: string\n slug: string\n displayName: string\n /** Vite-root-relative path to app bundle entry, if it exists */\n appBundlePath: string | null\n}\n\n/**\n * Discover all games from puzzmo.json files under a root directory.\n *\n * @internal\n */\nexport function discoverGames(viteRoot: string): Map<string, GameInfo> {\n const games = new Map<string, GameInfo>()\n const candidates = findPuzzmoJsonDirs(viteRoot, 3)\n if (fs.existsSync(path.join(viteRoot, \"puzzmo.json\"))) {\n candidates.unshift(viteRoot)\n }\n for (const dir of candidates) {\n try {\n const data = JSON.parse(fs.readFileSync(path.join(dir, \"puzzmo.json\"), \"utf-8\"))\n if (!data?.game?.slug) continue\n const bundleEntry = resolveBundleEntry(dir, \"src/appBundle\")\n let appBundle: string | null = null\n if (bundleEntry) {\n const relative = path.relative(viteRoot, bundleEntry)\n appBundle = \"/\" + relative.split(path.sep).join(\"/\")\n }\n games.set(data.game.slug, { dir, slug: data.game.slug, displayName: data.game.displayName, appBundlePath: appBundle })\n } catch {\n // skip invalid files\n }\n }\n return games\n}\n\n/**\n * Resolve which game a request belongs to using the referer URL.\n *\n * @internal\n */\nexport function resolveGameFromReferer(referer: string | undefined, games: Map<string, GameInfo>, viteRoot: string): GameInfo | undefined {\n if (referer) {\n try {\n const refPath = new URL(referer).pathname\n for (const g of games.values()) {\n const relDir = \"/\" + path.relative(viteRoot, g.dir).split(path.sep).join(\"/\")\n if (refPath.startsWith(relDir + \"/\") || refPath === relDir) return g\n }\n } catch {\n // ignore malformed referer\n }\n }\n if (games.size === 1) return games.values().next().value\n return undefined\n}\n\n/**\n * Generate the virtual module code for the simulator.\n *\n * @internal\n */\nexport function generateSimulatorCode(options: PuzzmoSimulatorPluginOptions, game: GameInfo | undefined): string {\n const { fixturesGlob: fixturesOpt, ...config } = options\n const fixturesGlob = fixturesOpt === false ? null : (fixturesOpt ?? \"/fixtures/puzzles/**/*.json\")\n\n const lines = [`import { createSimulator } from \"@puzzmo/sdk/simulator\"`]\n\n if (fixturesGlob) {\n lines.push(`const fixtures = import.meta.glob(${JSON.stringify(fixturesGlob)}, { eager: true })`)\n }\n\n if (game?.appBundlePath) {\n lines.push(`import(${JSON.stringify(game.appBundlePath)}).then(m => {`)\n lines.push(` if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail`)\n lines.push(`}).catch(() => {})`)\n }\n\n const simConfig = { ...config, ...(game?.slug ? { slug: game.slug } : {}) }\n const configEntries = Object.entries(simConfig).filter(([, v]) => v !== undefined)\n const configParts = configEntries.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)\n if (fixturesGlob) configParts.push(\"fixtures\")\n\n lines.push(`createSimulator({ ${configParts.join(\", \")} })`)\n\n return lines.join(\"\\n\")\n}\n\n/** Vite plugin that injects the Puzzmo simulator in dev mode and handles OAuth callbacks. */\nexport function puzzmoSimulator(options: PuzzmoSimulatorPluginOptions = {}): Plugin {\n let games = new Map<string, GameInfo>()\n let viteRoot: string\n\n return {\n name: \"puzzmo-simulator\",\n apply: \"serve\",\n\n configResolved(config: ResolvedConfig) {\n viteRoot = config.root\n games = discoverGames(viteRoot)\n\n if (games.size === 0) {\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m\\x1b[2m no puzzmo.json files found\\x1b[22m`)\n } else {\n const names = [...games.values()].map((g) => `\\x1b[36m${g.slug}\\x1b[39m`)\n const label = games.size === 1 ? \"game\" : \"games\"\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m found ${games.size} ${label}: ${names.join(\"\\x1b[2m, \\x1b[22m\")}`)\n }\n },\n\n resolveId(id) {\n if (id === virtualID || id.startsWith(virtualID + \"?\")) return \"\\0\" + id\n },\n\n load(id) {\n if (!id.startsWith(\"\\0\" + virtualID)) return\n const params = new URLSearchParams(id.split(\"?\")[1] || \"\")\n const gameSlug = params.get(\"game\")\n const game = gameSlug ? games.get(gameSlug) : games.size === 1 ? games.values().next().value : undefined\n return generateSimulatorCode(options, game)\n },\n\n configureServer(server) {\n server.middlewares.use(\"/oauth/callback\", (_req, res) => {\n res.setHeader(\"Content-Type\", \"text/html\")\n res.end(`<!DOCTYPE html>\n<html><head><title>Puzzmo OAuth</title></head>\n<body><script>\nvar params = new URLSearchParams(window.location.search);\nvar returnUrl = sessionStorage.getItem(\"oauth_return_url\") || \"/\";\nvar url = new URL(returnUrl);\nparams.forEach(function(v, k) { url.searchParams.set(k, v); });\nwindow.location.href = url.toString();\n</script></body></html>`)\n })\n\n // Serve the simulator init module, resolving the game from the referer\n server.middlewares.use(async (req, res, next) => {\n if (req.url?.split(\"?\")[0] !== simulatorURL) return next()\n\n const game = resolveGameFromReferer(req.headers.referer, games, viteRoot)\n const moduleID = virtualID + (game ? `?game=${game.slug}` : \"\")\n const result = await server.transformRequest(moduleID)\n if (!result) return next()\n res.setHeader(\"Content-Type\", \"application/javascript\")\n res.end(result.code)\n })\n },\n\n transformIndexHtml() {\n return [\n {\n tag: \"script\",\n attrs: { type: \"module\", src: simulatorURL },\n injectTo: \"head\",\n },\n ]\n },\n }\n}\n\ntype BundlePluginOptions = {\n /** Entry file for the bundle */\n entry: string\n /** Output file name */\n outputFile: string\n}\n\nfunction createBundlePlugin(pluginName: string, defaults: BundlePluginOptions) {\n return (options: Partial<BundlePluginOptions> = {}): Plugin => {\n const { entry, outputFile } = { ...defaults, ...options }\n return {\n name: pluginName,\n apply: \"build\",\n async closeBundle() {\n // If the caller overrode `entry`, honor it as-is. Otherwise try `.js` first, then `.ts`.\n const resolvedEntry = options.entry\n ? path.isAbsolute(entry)\n ? entry\n : path.resolve(process.cwd(), entry)\n : (resolveBundleEntry(process.cwd(), stripBundleExt(entry)) ?? path.resolve(process.cwd(), entry))\n try {\n await build({\n configFile: false,\n logLevel: \"warn\",\n build: {\n lib: {\n entry: resolvedEntry,\n formats: [\"es\"],\n fileName: () => outputFile,\n },\n outDir: \"dist\",\n emptyOutDir: false,\n },\n })\n } catch (error) {\n console.error(`[${pluginName}] build failed:`, error)\n throw error\n }\n },\n }\n }\n}\n\n/** Strip the trailing extension from a default entry path so we can probe siblings. */\nconst stripBundleExt = (p: string) => p.replace(/\\.[jt]sx?$/i, \"\")\n\n/** Returns the absolute path to the first matching extension under `dir`, or null. */\nconst resolveBundleEntry = (dir: string, baseRelative: string): string | null => {\n for (const ext of [\".js\", \".ts\"]) {\n const candidate = path.join(dir, baseRelative + ext)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nexport type AppBundlePluginOptions = Partial<BundlePluginOptions>\n\n/**\n * Vite plugin that produces dist/app-bundle.js after the main build for app-level integrations.\n *\n * The bundle exports `renderThumbnail(puzzleStr, inputStr?, config?)` — a pure\n * SVG-string renderer used by the Puzzmo platform for puzzle previews.\n */\nexport const appBundlePlugin = createBundlePlugin(\"app-bundle\", { entry: \"src/appBundle.js\", outputFile: \"app-bundle.js\" })\n\nexport type EditorBundlePluginOptions = Partial<BundlePluginOptions>\n\n/** Vite plugin that produces dist/editor-bundle.js after the main build for editor-level integrations. */\nexport const editorBundlePlugin = createBundlePlugin(\"editor-bundle\", { entry: \"src/editorBundle.js\", outputFile: \"editor-bundle.js\" })\n\n/**\n * Recursively find directories containing puzzmo.json, up to `maxDepth` levels deep.\n *\n * @internal\n */\nexport const findPuzzmoJsonDirs = (root: string, maxDepth: number, depth = 0): string[] => {\n if (depth >= maxDepth) return []\n const results: string[] = []\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(root, { withFileTypes: true })\n } catch {\n return results\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue\n const dir = path.join(root, entry.name)\n if (fs.existsSync(path.join(dir, \"puzzmo.json\"))) {\n results.push(dir)\n }\n results.push(...findPuzzmoJsonDirs(dir, maxDepth, depth + 1))\n }\n return results\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"vite.cjs","names":[],"sources":["../src/vite.ts"],"sourcesContent":["import type { Plugin, ResolvedConfig } from \"vite\"\nimport { build } from \"vite\"\nimport path from \"path\"\nimport fs from \"fs\"\n\nexport type PuzzmoSimulatorPluginOptions = {\n /** Whether to auto-start the game after READY (default: true) */\n autoStart?: boolean\n /** Initial collapsed state (default: true) */\n collapsed?: boolean\n /**\n * Glob pattern for fixture files, passed to import.meta.glob which is relative to the closest puzzmo.json. Defaults\n * to `\"/fixtures/puzzles/**\\/*.{json,toml}\"`. Fixtures are loaded as raw strings (any text format works — JSON,\n * TOML, or a custom format) and delivered to the game verbatim, so the game parses them itself. Pass false to disable.\n */\n fixturesGlob?: string | false\n}\n\nconst simulatorURL = \"/@puzzmo-simulator-init.js\"\nconst virtualID = \"virtual:puzzmo-simulator\"\n\n/** @internal */\nexport type GameInfo = {\n /** Directory containing the puzzmo.json */\n dir: string\n slug: string\n displayName: string\n /** Vite-root-relative path to app bundle entry, if it exists */\n appBundlePath: string | null\n}\n\n/**\n * Discover all games from puzzmo.json files under a root directory.\n *\n * @internal\n */\nexport function discoverGames(viteRoot: string): Map<string, GameInfo> {\n const games = new Map<string, GameInfo>()\n const candidates = findPuzzmoJsonDirs(viteRoot, 3)\n if (fs.existsSync(path.join(viteRoot, \"puzzmo.json\"))) {\n candidates.unshift(viteRoot)\n }\n for (const dir of candidates) {\n try {\n const data = JSON.parse(fs.readFileSync(path.join(dir, \"puzzmo.json\"), \"utf-8\"))\n if (!data?.game?.slug) continue\n const bundleEntry = resolveBundleEntry(dir, \"src/appBundle\")\n let appBundle: string | null = null\n if (bundleEntry) {\n const relative = path.relative(viteRoot, bundleEntry)\n appBundle = \"/\" + relative.split(path.sep).join(\"/\")\n }\n games.set(data.game.slug, { dir, slug: data.game.slug, displayName: data.game.displayName, appBundlePath: appBundle })\n } catch {\n // skip invalid files\n }\n }\n return games\n}\n\n/**\n * Resolve which game a request belongs to using the referer URL.\n *\n * @internal\n */\nexport function resolveGameFromReferer(referer: string | undefined, games: Map<string, GameInfo>, viteRoot: string): GameInfo | undefined {\n if (referer) {\n try {\n const refPath = new URL(referer).pathname\n for (const g of games.values()) {\n const relDir = \"/\" + path.relative(viteRoot, g.dir).split(path.sep).join(\"/\")\n if (refPath.startsWith(relDir + \"/\") || refPath === relDir) return g\n }\n } catch {\n // ignore malformed referer\n }\n }\n if (games.size === 1) return games.values().next().value\n return undefined\n}\n\n/**\n * Generate the virtual module code for the simulator.\n *\n * @internal\n */\nexport function generateSimulatorCode(options: PuzzmoSimulatorPluginOptions, game: GameInfo | undefined): string {\n const { fixturesGlob: fixturesOpt, ...config } = options\n const fixturesGlob = fixturesOpt === false ? null : (fixturesOpt ?? \"/fixtures/puzzles/**/*.{json,toml}\")\n\n const lines = [`import { createSimulator } from \"@puzzmo/sdk/simulator\"`]\n\n // Load fixtures as raw strings so any text format reaches the game verbatim; the game does its own parsing.\n if (fixturesGlob) {\n lines.push(`const fixtures = import.meta.glob(${JSON.stringify(fixturesGlob)}, { query: \"?raw\", import: \"default\", eager: true })`)\n }\n\n if (game?.appBundlePath) {\n lines.push(`import(${JSON.stringify(game.appBundlePath)}).then(m => {`)\n lines.push(` if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail`)\n lines.push(`}).catch(() => {})`)\n }\n\n const simConfig = { ...config, ...(game?.slug ? { slug: game.slug } : {}) }\n const configEntries = Object.entries(simConfig).filter(([, v]) => v !== undefined)\n const configParts = configEntries.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)\n if (fixturesGlob) configParts.push(\"fixtures\")\n\n lines.push(`createSimulator({ ${configParts.join(\", \")} })`)\n\n return lines.join(\"\\n\")\n}\n\n/** Vite plugin that injects the Puzzmo simulator in dev mode and handles OAuth callbacks. */\nexport function puzzmoSimulator(options: PuzzmoSimulatorPluginOptions = {}): Plugin {\n let games = new Map<string, GameInfo>()\n let viteRoot: string\n\n return {\n name: \"puzzmo-simulator\",\n apply: \"serve\",\n\n configResolved(config: ResolvedConfig) {\n viteRoot = config.root\n games = discoverGames(viteRoot)\n\n if (games.size === 0) {\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m\\x1b[2m no puzzmo.json files found\\x1b[22m`)\n } else {\n const names = [...games.values()].map((g) => `\\x1b[36m${g.slug}\\x1b[39m`)\n const label = games.size === 1 ? \"game\" : \"games\"\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m found ${games.size} ${label}: ${names.join(\"\\x1b[2m, \\x1b[22m\")}`)\n }\n },\n\n resolveId(id) {\n if (id === virtualID || id.startsWith(virtualID + \"?\")) return \"\\0\" + id\n },\n\n load(id) {\n if (!id.startsWith(\"\\0\" + virtualID)) return\n const params = new URLSearchParams(id.split(\"?\")[1] || \"\")\n const gameSlug = params.get(\"game\")\n const game = gameSlug ? games.get(gameSlug) : games.size === 1 ? games.values().next().value : undefined\n return generateSimulatorCode(options, game)\n },\n\n configureServer(server) {\n server.middlewares.use(\"/oauth/callback\", (_req, res) => {\n res.setHeader(\"Content-Type\", \"text/html\")\n res.end(`<!DOCTYPE html>\n<html><head><title>Puzzmo OAuth</title></head>\n<body><script>\nvar params = new URLSearchParams(window.location.search);\nvar returnUrl = sessionStorage.getItem(\"oauth_return_url\") || \"/\";\nvar url = new URL(returnUrl);\nparams.forEach(function(v, k) { url.searchParams.set(k, v); });\nwindow.location.href = url.toString();\n</script></body></html>`)\n })\n\n // Serve the simulator init module, resolving the game from the referer\n server.middlewares.use(async (req, res, next) => {\n if (req.url?.split(\"?\")[0] !== simulatorURL) return next()\n\n const game = resolveGameFromReferer(req.headers.referer, games, viteRoot)\n const moduleID = virtualID + (game ? `?game=${game.slug}` : \"\")\n const result = await server.transformRequest(moduleID)\n if (!result) return next()\n res.setHeader(\"Content-Type\", \"application/javascript\")\n res.end(result.code)\n })\n },\n\n transformIndexHtml() {\n return [\n {\n tag: \"script\",\n attrs: { type: \"module\", src: simulatorURL },\n injectTo: \"head\",\n },\n ]\n },\n }\n}\n\ntype BundlePluginOptions = {\n /** Entry file for the bundle */\n entry: string\n /** Output file name */\n outputFile: string\n}\n\nfunction createBundlePlugin(pluginName: string, defaults: BundlePluginOptions) {\n return (options: Partial<BundlePluginOptions> = {}): Plugin => {\n const { entry, outputFile } = { ...defaults, ...options }\n return {\n name: pluginName,\n apply: \"build\",\n async closeBundle() {\n // If the caller overrode `entry`, honor it as-is. Otherwise try `.js` first, then `.ts`.\n const resolvedEntry = options.entry\n ? path.isAbsolute(entry)\n ? entry\n : path.resolve(process.cwd(), entry)\n : (resolveBundleEntry(process.cwd(), stripBundleExt(entry)) ?? path.resolve(process.cwd(), entry))\n try {\n await build({\n configFile: false,\n logLevel: \"warn\",\n build: {\n lib: {\n entry: resolvedEntry,\n formats: [\"es\"],\n fileName: () => outputFile,\n },\n outDir: \"dist\",\n emptyOutDir: false,\n },\n })\n } catch (error) {\n console.error(`[${pluginName}] build failed:`, error)\n throw error\n }\n },\n }\n }\n}\n\n/** Strip the trailing extension from a default entry path so we can probe siblings. */\nconst stripBundleExt = (p: string) => p.replace(/\\.[jt]sx?$/i, \"\")\n\n/** Returns the absolute path to the first matching extension under `dir`, or null. */\nconst resolveBundleEntry = (dir: string, baseRelative: string): string | null => {\n for (const ext of [\".js\", \".ts\"]) {\n const candidate = path.join(dir, baseRelative + ext)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nexport type AppBundlePluginOptions = Partial<BundlePluginOptions>\n\n/**\n * Vite plugin that produces dist/app-bundle.js after the main build for app-level integrations.\n *\n * The bundle exports `renderThumbnail(puzzleStr, inputStr?, config?)` — a pure\n * SVG-string renderer used by the Puzzmo platform for puzzle previews.\n */\nexport const appBundlePlugin = createBundlePlugin(\"app-bundle\", { entry: \"src/appBundle.js\", outputFile: \"app-bundle.js\" })\n\nexport type EditorBundlePluginOptions = Partial<BundlePluginOptions>\n\n/** Vite plugin that produces dist/editor-bundle.js after the main build for editor-level integrations. */\nexport const editorBundlePlugin = createBundlePlugin(\"editor-bundle\", { entry: \"src/editorBundle.js\", outputFile: \"editor-bundle.js\" })\n\n/**\n * Recursively find directories containing puzzmo.json, up to `maxDepth` levels deep.\n *\n * @internal\n */\nexport const findPuzzmoJsonDirs = (root: string, maxDepth: number, depth = 0): string[] => {\n if (depth >= maxDepth) return []\n const results: string[] = []\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(root, { withFileTypes: true })\n } catch {\n return results\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue\n const dir = path.join(root, entry.name)\n if (fs.existsSync(path.join(dir, \"puzzmo.json\"))) {\n results.push(dir)\n }\n results.push(...findPuzzmoJsonDirs(dir, maxDepth, depth + 1))\n }\n return results\n}\n"],"mappings":"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"}
package/dist/vite.d.ts CHANGED
@@ -5,8 +5,9 @@ export type PuzzmoSimulatorPluginOptions = {
5
5
  /** Initial collapsed state (default: true) */
6
6
  collapsed?: boolean;
7
7
  /**
8
- * Glob pattern for fixture files, passed to import.meta.glob which is relative to the closest puzzmo.json. Defaults to
9
- * `"/fixtures/puzzles/**\/*.json"`. Pass false to disable.
8
+ * Glob pattern for fixture files, passed to import.meta.glob which is relative to the closest puzzmo.json. Defaults
9
+ * to `"/fixtures/puzzles/**\/*.{json,toml}"`. Fixtures are loaded as raw strings (any text format works — JSON,
10
+ * TOML, or a custom format) and delivered to the game verbatim, so the game parses them itself. Pass false to disable.
10
11
  */
11
12
  fixturesGlob?: string | false;
12
13
  };
@@ -1 +1 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAA;AAKlD,MAAM,MAAM,4BAA4B,GAAG;IACzC,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAC9B,CAAA;AAKD,gBAAgB;AAChB,MAAM,MAAM,QAAQ,GAAG;IACrB,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAsBrE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAcxI;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAwB/G;AAED,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,OAAO,GAAE,4BAAiC,GAAG,MAAM,CAsElF;AAED,KAAK,mBAAmB,GAAG;IACzB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAkDD,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;AAEjE;;;;;GAKG;AACH,eAAO,MAAM,eAAe,yDAA+F,CAAA;AAE3H,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;AAEpE,0GAA0G;AAC1G,eAAO,MAAM,kBAAkB,yDAAwG,CAAA;AAEvI;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,8DAkB9B,CAAA"}
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAA;AAKlD,MAAM,MAAM,4BAA4B,GAAG;IACzC,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAC9B,CAAA;AAKD,gBAAgB;AAChB,MAAM,MAAM,QAAQ,GAAG;IACrB,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAsBrE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAcxI;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAyB/G;AAED,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,OAAO,GAAE,4BAAiC,GAAG,MAAM,CAsElF;AAED,KAAK,mBAAmB,GAAG;IACzB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAkDD,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;AAEjE;;;;;GAKG;AACH,eAAO,MAAM,eAAe,yDAA+F,CAAA;AAE3H,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;AAEpE,0GAA0G;AAC1G,eAAO,MAAM,kBAAkB,yDAAwG,CAAA;AAEvI;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,8DAkB9B,CAAA"}
package/dist/vite.js CHANGED
@@ -65,8 +65,8 @@ function d(e, t, n) {
65
65
  * @internal
66
66
  */
67
67
  function f(e, n) {
68
- let { fixturesGlob: r } = e, i = o(e, s), a = r === !1 ? null : r == null ? "/fixtures/puzzles/**/*.json" : r, c = ["import { createSimulator } from \"@puzzmo/sdk/simulator\""];
69
- a && c.push(`const fixtures = import.meta.glob(${JSON.stringify(a)}, { eager: true })`), n != null && n.appBundlePath && (c.push(`import(${JSON.stringify(n.appBundlePath)}).then(m => {`), c.push(" if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail"), c.push("}).catch(() => {})"));
68
+ let { fixturesGlob: r } = e, i = o(e, s), a = r === !1 ? null : r == null ? "/fixtures/puzzles/**/*.{json,toml}" : r, c = ["import { createSimulator } from \"@puzzmo/sdk/simulator\""];
69
+ a && c.push(`const fixtures = import.meta.glob(${JSON.stringify(a)}, { query: "?raw", import: "default", eager: true })`), n != null && n.appBundlePath && (c.push(`import(${JSON.stringify(n.appBundlePath)}).then(m => {`), c.push(" if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail"), c.push("}).catch(() => {})"));
70
70
  let l = t(t({}, i), n != null && n.slug ? { slug: n.slug } : {}), u = Object.entries(l).filter(([, e]) => e !== void 0).map(([e, t]) => `${e}: ${JSON.stringify(t)}`);
71
71
  return a && u.push("fixtures"), c.push(`createSimulator({ ${u.join(", ")} })`), c.join("\n");
72
72
  }
package/dist/vite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","names":[],"sources":["../src/vite.ts"],"sourcesContent":["import type { Plugin, ResolvedConfig } from \"vite\"\nimport { build } from \"vite\"\nimport path from \"path\"\nimport fs from \"fs\"\n\nexport type PuzzmoSimulatorPluginOptions = {\n /** Whether to auto-start the game after READY (default: true) */\n autoStart?: boolean\n /** Initial collapsed state (default: true) */\n collapsed?: boolean\n /**\n * Glob pattern for fixture files, passed to import.meta.glob which is relative to the closest puzzmo.json. Defaults to\n * `\"/fixtures/puzzles/**\\/*.json\"`. Pass false to disable.\n */\n fixturesGlob?: string | false\n}\n\nconst simulatorURL = \"/@puzzmo-simulator-init.js\"\nconst virtualID = \"virtual:puzzmo-simulator\"\n\n/** @internal */\nexport type GameInfo = {\n /** Directory containing the puzzmo.json */\n dir: string\n slug: string\n displayName: string\n /** Vite-root-relative path to app bundle entry, if it exists */\n appBundlePath: string | null\n}\n\n/**\n * Discover all games from puzzmo.json files under a root directory.\n *\n * @internal\n */\nexport function discoverGames(viteRoot: string): Map<string, GameInfo> {\n const games = new Map<string, GameInfo>()\n const candidates = findPuzzmoJsonDirs(viteRoot, 3)\n if (fs.existsSync(path.join(viteRoot, \"puzzmo.json\"))) {\n candidates.unshift(viteRoot)\n }\n for (const dir of candidates) {\n try {\n const data = JSON.parse(fs.readFileSync(path.join(dir, \"puzzmo.json\"), \"utf-8\"))\n if (!data?.game?.slug) continue\n const bundleEntry = resolveBundleEntry(dir, \"src/appBundle\")\n let appBundle: string | null = null\n if (bundleEntry) {\n const relative = path.relative(viteRoot, bundleEntry)\n appBundle = \"/\" + relative.split(path.sep).join(\"/\")\n }\n games.set(data.game.slug, { dir, slug: data.game.slug, displayName: data.game.displayName, appBundlePath: appBundle })\n } catch {\n // skip invalid files\n }\n }\n return games\n}\n\n/**\n * Resolve which game a request belongs to using the referer URL.\n *\n * @internal\n */\nexport function resolveGameFromReferer(referer: string | undefined, games: Map<string, GameInfo>, viteRoot: string): GameInfo | undefined {\n if (referer) {\n try {\n const refPath = new URL(referer).pathname\n for (const g of games.values()) {\n const relDir = \"/\" + path.relative(viteRoot, g.dir).split(path.sep).join(\"/\")\n if (refPath.startsWith(relDir + \"/\") || refPath === relDir) return g\n }\n } catch {\n // ignore malformed referer\n }\n }\n if (games.size === 1) return games.values().next().value\n return undefined\n}\n\n/**\n * Generate the virtual module code for the simulator.\n *\n * @internal\n */\nexport function generateSimulatorCode(options: PuzzmoSimulatorPluginOptions, game: GameInfo | undefined): string {\n const { fixturesGlob: fixturesOpt, ...config } = options\n const fixturesGlob = fixturesOpt === false ? null : (fixturesOpt ?? \"/fixtures/puzzles/**/*.json\")\n\n const lines = [`import { createSimulator } from \"@puzzmo/sdk/simulator\"`]\n\n if (fixturesGlob) {\n lines.push(`const fixtures = import.meta.glob(${JSON.stringify(fixturesGlob)}, { eager: true })`)\n }\n\n if (game?.appBundlePath) {\n lines.push(`import(${JSON.stringify(game.appBundlePath)}).then(m => {`)\n lines.push(` if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail`)\n lines.push(`}).catch(() => {})`)\n }\n\n const simConfig = { ...config, ...(game?.slug ? { slug: game.slug } : {}) }\n const configEntries = Object.entries(simConfig).filter(([, v]) => v !== undefined)\n const configParts = configEntries.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)\n if (fixturesGlob) configParts.push(\"fixtures\")\n\n lines.push(`createSimulator({ ${configParts.join(\", \")} })`)\n\n return lines.join(\"\\n\")\n}\n\n/** Vite plugin that injects the Puzzmo simulator in dev mode and handles OAuth callbacks. */\nexport function puzzmoSimulator(options: PuzzmoSimulatorPluginOptions = {}): Plugin {\n let games = new Map<string, GameInfo>()\n let viteRoot: string\n\n return {\n name: \"puzzmo-simulator\",\n apply: \"serve\",\n\n configResolved(config: ResolvedConfig) {\n viteRoot = config.root\n games = discoverGames(viteRoot)\n\n if (games.size === 0) {\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m\\x1b[2m no puzzmo.json files found\\x1b[22m`)\n } else {\n const names = [...games.values()].map((g) => `\\x1b[36m${g.slug}\\x1b[39m`)\n const label = games.size === 1 ? \"game\" : \"games\"\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m found ${games.size} ${label}: ${names.join(\"\\x1b[2m, \\x1b[22m\")}`)\n }\n },\n\n resolveId(id) {\n if (id === virtualID || id.startsWith(virtualID + \"?\")) return \"\\0\" + id\n },\n\n load(id) {\n if (!id.startsWith(\"\\0\" + virtualID)) return\n const params = new URLSearchParams(id.split(\"?\")[1] || \"\")\n const gameSlug = params.get(\"game\")\n const game = gameSlug ? games.get(gameSlug) : games.size === 1 ? games.values().next().value : undefined\n return generateSimulatorCode(options, game)\n },\n\n configureServer(server) {\n server.middlewares.use(\"/oauth/callback\", (_req, res) => {\n res.setHeader(\"Content-Type\", \"text/html\")\n res.end(`<!DOCTYPE html>\n<html><head><title>Puzzmo OAuth</title></head>\n<body><script>\nvar params = new URLSearchParams(window.location.search);\nvar returnUrl = sessionStorage.getItem(\"oauth_return_url\") || \"/\";\nvar url = new URL(returnUrl);\nparams.forEach(function(v, k) { url.searchParams.set(k, v); });\nwindow.location.href = url.toString();\n</script></body></html>`)\n })\n\n // Serve the simulator init module, resolving the game from the referer\n server.middlewares.use(async (req, res, next) => {\n if (req.url?.split(\"?\")[0] !== simulatorURL) return next()\n\n const game = resolveGameFromReferer(req.headers.referer, games, viteRoot)\n const moduleID = virtualID + (game ? `?game=${game.slug}` : \"\")\n const result = await server.transformRequest(moduleID)\n if (!result) return next()\n res.setHeader(\"Content-Type\", \"application/javascript\")\n res.end(result.code)\n })\n },\n\n transformIndexHtml() {\n return [\n {\n tag: \"script\",\n attrs: { type: \"module\", src: simulatorURL },\n injectTo: \"head\",\n },\n ]\n },\n }\n}\n\ntype BundlePluginOptions = {\n /** Entry file for the bundle */\n entry: string\n /** Output file name */\n outputFile: string\n}\n\nfunction createBundlePlugin(pluginName: string, defaults: BundlePluginOptions) {\n return (options: Partial<BundlePluginOptions> = {}): Plugin => {\n const { entry, outputFile } = { ...defaults, ...options }\n return {\n name: pluginName,\n apply: \"build\",\n async closeBundle() {\n // If the caller overrode `entry`, honor it as-is. Otherwise try `.js` first, then `.ts`.\n const resolvedEntry = options.entry\n ? path.isAbsolute(entry)\n ? entry\n : path.resolve(process.cwd(), entry)\n : (resolveBundleEntry(process.cwd(), stripBundleExt(entry)) ?? path.resolve(process.cwd(), entry))\n try {\n await build({\n configFile: false,\n logLevel: \"warn\",\n build: {\n lib: {\n entry: resolvedEntry,\n formats: [\"es\"],\n fileName: () => outputFile,\n },\n outDir: \"dist\",\n emptyOutDir: false,\n },\n })\n } catch (error) {\n console.error(`[${pluginName}] build failed:`, error)\n throw error\n }\n },\n }\n }\n}\n\n/** Strip the trailing extension from a default entry path so we can probe siblings. */\nconst stripBundleExt = (p: string) => p.replace(/\\.[jt]sx?$/i, \"\")\n\n/** Returns the absolute path to the first matching extension under `dir`, or null. */\nconst resolveBundleEntry = (dir: string, baseRelative: string): string | null => {\n for (const ext of [\".js\", \".ts\"]) {\n const candidate = path.join(dir, baseRelative + ext)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nexport type AppBundlePluginOptions = Partial<BundlePluginOptions>\n\n/**\n * Vite plugin that produces dist/app-bundle.js after the main build for app-level integrations.\n *\n * The bundle exports `renderThumbnail(puzzleStr, inputStr?, config?)` — a pure\n * SVG-string renderer used by the Puzzmo platform for puzzle previews.\n */\nexport const appBundlePlugin = createBundlePlugin(\"app-bundle\", { entry: \"src/appBundle.js\", outputFile: \"app-bundle.js\" })\n\nexport type EditorBundlePluginOptions = Partial<BundlePluginOptions>\n\n/** Vite plugin that produces dist/editor-bundle.js after the main build for editor-level integrations. */\nexport const editorBundlePlugin = createBundlePlugin(\"editor-bundle\", { entry: \"src/editorBundle.js\", outputFile: \"editor-bundle.js\" })\n\n/**\n * Recursively find directories containing puzzmo.json, up to `maxDepth` levels deep.\n *\n * @internal\n */\nexport const findPuzzmoJsonDirs = (root: string, maxDepth: number, depth = 0): string[] => {\n if (depth >= maxDepth) return []\n const results: string[] = []\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(root, { withFileTypes: true })\n } catch {\n return results\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue\n const dir = path.join(root, entry.name)\n if (fs.existsSync(path.join(dir, \"puzzmo.json\"))) {\n results.push(dir)\n }\n results.push(...findPuzzmoJsonDirs(dir, maxDepth, depth + 1))\n }\n return results\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;SAsFU,eAAA,EArEJ,IAAe,8BACf,IAAY;;;;;;AAiBlB,SAAgB,EAAc,GAAyC;CACrE,IAAM,oBAAQ,IAAI,KAAuB,EACnC,IAAa,EAAmB,GAAU,EAAE;AAClD,CAAI,EAAG,WAAW,EAAK,KAAK,GAAU,cAAc,CAAC,IACnD,EAAW,QAAQ,EAAS;AAE9B,MAAK,IAAM,KAAO,EAChB,KAAI;;EACF,IAAM,IAAO,KAAK,MAAM,EAAG,aAAa,EAAK,KAAK,GAAK,cAAc,EAAE,QAAQ,CAAC;AAChF,MAAI,EAAA,OAAA,SAAA,IAAC,EAAM,SAAA,SAAA,EAAM,MAAM;EACvB,IAAM,IAAc,EAAmB,GAAK,gBAAgB,EACxD,IAA2B;AAK/B,EAJI,MAEF,IAAY,MADK,EAAK,SAAS,GAAU,EAAY,CAC1B,MAAM,EAAK,IAAI,CAAC,KAAK,IAAI,GAEtD,EAAM,IAAI,EAAK,KAAK,MAAM;GAAE;GAAK,MAAM,EAAK,KAAK;GAAM,aAAa,EAAK,KAAK;GAAa,eAAe;GAAW,CAAC;aAChH;AAIV,QAAO;;;;;;;AAQT,SAAgB,EAAuB,GAA6B,GAA8B,GAAwC;AACxI,KAAI,EACF,KAAI;EACF,IAAM,IAAU,IAAI,IAAI,EAAQ,CAAC;AACjC,OAAK,IAAM,KAAK,EAAM,QAAQ,EAAE;GAC9B,IAAM,IAAS,MAAM,EAAK,SAAS,GAAU,EAAE,IAAI,CAAC,MAAM,EAAK,IAAI,CAAC,KAAK,IAAI;AAC7E,OAAI,EAAQ,WAAW,IAAS,IAAI,IAAI,MAAY,EAAQ,QAAO;;aAE/D;AAIV,KAAI,EAAM,SAAS,EAAG,QAAO,EAAM,QAAQ,CAAC,MAAM,CAAC;;;;;;;AASrD,SAAgB,EAAsB,GAAuC,GAAoC;CAC/G,IAAM,EAAE,cAAc,MAAA,GAAgB,IAAA,EAAW,GAAA,EAAA,EAC3C,IAAe,MAAgB,KAAQ,OAAQ,KAAA,OAAe,gCAAf,GAE/C,IAAQ,CAAC,4DAA0D;AAMzE,CAJI,KACF,EAAM,KAAK,qCAAqC,KAAK,UAAU,EAAa,CAAC,oBAAoB,EAGnG,KAAA,QAAI,EAAM,kBACR,EAAM,KAAK,UAAU,KAAK,UAAU,EAAK,cAAc,CAAC,eAAe,EACvE,EAAM,KAAK,0EAA0E,EACrF,EAAM,KAAK,qBAAqB;CAGlC,IAAM,IAAA,EAAA,EAAA,EAAA,EAAiB,EAAA,EAAA,KAAA,QAAY,EAAM,OAAO,EAAE,MAAM,EAAK,MAAM,GAAG,EAAE,CAAG,EAErE,IADgB,OAAO,QAAQ,EAAU,CAAC,QAAQ,GAAG,OAAO,MAAM,KAAA,EAAU,CAChD,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,IAAI,KAAK,UAAU,EAAE,GAAG;AAK/E,QAJI,KAAc,EAAY,KAAK,WAAW,EAE9C,EAAM,KAAK,qBAAqB,EAAY,KAAK,KAAK,CAAC,KAAK,EAErD,EAAM,KAAK,KAAK;;;AAIzB,SAAgB,EAAgB,IAAwC,EAAE,EAAU;CAClF,IAAI,oBAAQ,IAAI,KAAuB,EACnC;AAEJ,QAAO;EACL,MAAM;EACN,OAAO;EAEP,eAAe,GAAwB;AAIrC,OAHA,IAAW,EAAO,MAClB,IAAQ,EAAc,EAAS,EAE3B,EAAM,SAAS,EACjB,GAAO,OAAO,KAAK,qFAAqF;QACnG;IACL,IAAM,IAAQ,CAAC,GAAG,EAAM,QAAQ,CAAC,CAAC,KAAK,MAAM,WAAW,EAAE,KAAK,UAAU,EACnE,IAAQ,EAAM,SAAS,IAAI,SAAS;AAC1C,MAAO,OAAO,KAAK,kDAAkD,EAAM,KAAK,GAAG,EAAM,IAAI,EAAM,KAAK,oBAAoB,GAAG;;;EAInI,UAAU,GAAI;AACZ,OAAI,MAAO,KAAa,EAAG,WAAW,IAAY,IAAI,CAAE,QAAO,OAAO;;EAGxE,KAAK,GAAI;AACP,OAAI,CAAC,EAAG,WAAW,OAAO,EAAU,CAAE;GAEtC,IAAM,IADS,IAAI,gBAAgB,EAAG,MAAM,IAAI,CAAC,MAAM,GAAG,CAClC,IAAI,OAAO;AAEnC,UAAO,EAAsB,GADhB,IAAW,EAAM,IAAI,EAAS,GAAG,EAAM,SAAS,IAAI,EAAM,QAAQ,CAAC,MAAM,CAAC,QAAQ,KAAA,EACpD;;EAG7C,gBAAgB,GAAQ;AAetB,GAdA,EAAO,YAAY,IAAI,oBAAoB,GAAM,MAAQ;AAEvD,IADA,EAAI,UAAU,gBAAgB,YAAY,EAC1C,EAAI,IAAI,uXAQS;KACjB,EAGF,EAAO,YAAY,IAAA,WAAA;yBAAW,GAAK,GAAK,GAAS;;AAC/C,WAAA,IAAI,EAAI,QAAA,OAAA,KAAA,IAAA,EAAK,MAAM,IAAI,CAAC,QAAO,EAAc,QAAO,GAAM;KAE1D,IAAM,IAAO,EAAuB,EAAI,QAAQ,SAAS,GAAO,EAAS,EACnE,IAAW,KAAa,IAAO,SAAS,EAAK,SAAS,KACtD,IAAS,MAAM,EAAO,iBAAiB,EAAS;AACtD,SAAI,CAAC,EAAQ,QAAO,GAAM;AAE1B,KADA,EAAI,UAAU,gBAAgB,yBAAyB,EACvD,EAAI,IAAI,EAAO,KAAK;;oBARQ,GAAK,GAAK,GAAA;;;OAStC;;EAGJ,qBAAqB;AACnB,UAAO,CACL;IACE,KAAK;IACL,OAAO;KAAE,MAAM;KAAU,KAAK;KAAc;IAC5C,UAAU;IACX,CACF;;EAEJ;;AAUH,SAAS,EAAmB,GAAoB,GAA+B;AAC7E,SAAQ,IAAwC,EAAE,KAAa;EAC7D,IAAM,EAAE,UAAO,kBAAA,EAAA,EAAA,EAAA,EAAoB,EAAA,EAAa,EAAS;AACzD,SAAO;GACL,MAAM;GACN,OAAO;GACP,cAAM;0BAAc;;KAElB,IAAM,IAAgB,EAAQ,QAC1B,EAAK,WAAW,EAAM,GACpB,IACA,EAAK,QAAQ,QAAQ,KAAK,EAAE,EAAM,IAAA,IACnC,EAAmB,QAAQ,KAAK,EAAE,EAAe,EAAM,CAAC,KAAA,OAAI,EAAK,QAAQ,QAAQ,KAAK,EAAE,EAAM,GAAtC;AAC7D,SAAI;AACF,YAAM,EAAM;OACV,YAAY;OACZ,UAAU;OACV,OAAO;QACL,KAAK;SACH,OAAO;SACP,SAAS,CAAC,KAAK;SACf,gBAAgB;SACjB;QACD,QAAQ;QACR,aAAa;QACd;OACF,CAAC;cACK,GAAO;AAEd,YADA,QAAQ,MAAM,IAAI,EAAW,kBAAkB,EAAM,EAC/C;;;;GAGX;;;;AAKL,IAAM,KAAkB,MAAc,EAAE,QAAQ,eAAe,GAAG,EAG5D,KAAsB,GAAa,MAAwC;AAC/E,MAAK,IAAM,KAAO,CAAC,OAAO,MAAM,EAAE;EAChC,IAAM,IAAY,EAAK,KAAK,GAAK,IAAe,EAAI;AACpD,MAAI,EAAG,WAAW,EAAU,CAAE,QAAO;;AAEvC,QAAO;;;;;;;;AAWT,MAAa,IAAkB,EAAmB,cAAc;CAAE,OAAO;CAAoB,YAAY;CAAiB,CAAC,EAK9G,IAAqB,EAAmB,iBAAiB;CAAE,OAAO;CAAuB,YAAY;CAAoB,CAAC,EAO1H,KAAsB,GAAc,GAAkB,IAAQ,MAAgB;AACzF,KAAI,KAAS,EAAU,QAAO,EAAE;CAChC,IAAM,IAAoB,EAAE,EACxB;AACJ,KAAI;AACF,MAAU,EAAG,YAAY,GAAM,EAAE,eAAe,IAAM,CAAC;aACjD;AACN,SAAO;;AAET,MAAK,IAAM,KAAS,GAAS;AAC3B,MAAI,CAAC,EAAM,aAAa,IAAI,EAAM,KAAK,WAAW,IAAI,IAAI,EAAM,SAAS,eAAgB;EACzF,IAAM,IAAM,EAAK,KAAK,GAAM,EAAM,KAAK;AAIvC,EAHI,EAAG,WAAW,EAAK,KAAK,GAAK,cAAc,CAAC,IAC9C,EAAQ,KAAK,EAAI,EAEnB,EAAQ,KAAK,GAAG,EAAmB,GAAK,GAAU,IAAQ,EAAE,CAAC;;AAE/D,QAAO"}
1
+ {"version":3,"file":"vite.js","names":[],"sources":["../src/vite.ts"],"sourcesContent":["import type { Plugin, ResolvedConfig } from \"vite\"\nimport { build } from \"vite\"\nimport path from \"path\"\nimport fs from \"fs\"\n\nexport type PuzzmoSimulatorPluginOptions = {\n /** Whether to auto-start the game after READY (default: true) */\n autoStart?: boolean\n /** Initial collapsed state (default: true) */\n collapsed?: boolean\n /**\n * Glob pattern for fixture files, passed to import.meta.glob which is relative to the closest puzzmo.json. Defaults\n * to `\"/fixtures/puzzles/**\\/*.{json,toml}\"`. Fixtures are loaded as raw strings (any text format works — JSON,\n * TOML, or a custom format) and delivered to the game verbatim, so the game parses them itself. Pass false to disable.\n */\n fixturesGlob?: string | false\n}\n\nconst simulatorURL = \"/@puzzmo-simulator-init.js\"\nconst virtualID = \"virtual:puzzmo-simulator\"\n\n/** @internal */\nexport type GameInfo = {\n /** Directory containing the puzzmo.json */\n dir: string\n slug: string\n displayName: string\n /** Vite-root-relative path to app bundle entry, if it exists */\n appBundlePath: string | null\n}\n\n/**\n * Discover all games from puzzmo.json files under a root directory.\n *\n * @internal\n */\nexport function discoverGames(viteRoot: string): Map<string, GameInfo> {\n const games = new Map<string, GameInfo>()\n const candidates = findPuzzmoJsonDirs(viteRoot, 3)\n if (fs.existsSync(path.join(viteRoot, \"puzzmo.json\"))) {\n candidates.unshift(viteRoot)\n }\n for (const dir of candidates) {\n try {\n const data = JSON.parse(fs.readFileSync(path.join(dir, \"puzzmo.json\"), \"utf-8\"))\n if (!data?.game?.slug) continue\n const bundleEntry = resolveBundleEntry(dir, \"src/appBundle\")\n let appBundle: string | null = null\n if (bundleEntry) {\n const relative = path.relative(viteRoot, bundleEntry)\n appBundle = \"/\" + relative.split(path.sep).join(\"/\")\n }\n games.set(data.game.slug, { dir, slug: data.game.slug, displayName: data.game.displayName, appBundlePath: appBundle })\n } catch {\n // skip invalid files\n }\n }\n return games\n}\n\n/**\n * Resolve which game a request belongs to using the referer URL.\n *\n * @internal\n */\nexport function resolveGameFromReferer(referer: string | undefined, games: Map<string, GameInfo>, viteRoot: string): GameInfo | undefined {\n if (referer) {\n try {\n const refPath = new URL(referer).pathname\n for (const g of games.values()) {\n const relDir = \"/\" + path.relative(viteRoot, g.dir).split(path.sep).join(\"/\")\n if (refPath.startsWith(relDir + \"/\") || refPath === relDir) return g\n }\n } catch {\n // ignore malformed referer\n }\n }\n if (games.size === 1) return games.values().next().value\n return undefined\n}\n\n/**\n * Generate the virtual module code for the simulator.\n *\n * @internal\n */\nexport function generateSimulatorCode(options: PuzzmoSimulatorPluginOptions, game: GameInfo | undefined): string {\n const { fixturesGlob: fixturesOpt, ...config } = options\n const fixturesGlob = fixturesOpt === false ? null : (fixturesOpt ?? \"/fixtures/puzzles/**/*.{json,toml}\")\n\n const lines = [`import { createSimulator } from \"@puzzmo/sdk/simulator\"`]\n\n // Load fixtures as raw strings so any text format reaches the game verbatim; the game does its own parsing.\n if (fixturesGlob) {\n lines.push(`const fixtures = import.meta.glob(${JSON.stringify(fixturesGlob)}, { query: \"?raw\", import: \"default\", eager: true })`)\n }\n\n if (game?.appBundlePath) {\n lines.push(`import(${JSON.stringify(game.appBundlePath)}).then(m => {`)\n lines.push(` if (m.renderThumbnail) globalThis.renderThumbnail = m.renderThumbnail`)\n lines.push(`}).catch(() => {})`)\n }\n\n const simConfig = { ...config, ...(game?.slug ? { slug: game.slug } : {}) }\n const configEntries = Object.entries(simConfig).filter(([, v]) => v !== undefined)\n const configParts = configEntries.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)\n if (fixturesGlob) configParts.push(\"fixtures\")\n\n lines.push(`createSimulator({ ${configParts.join(\", \")} })`)\n\n return lines.join(\"\\n\")\n}\n\n/** Vite plugin that injects the Puzzmo simulator in dev mode and handles OAuth callbacks. */\nexport function puzzmoSimulator(options: PuzzmoSimulatorPluginOptions = {}): Plugin {\n let games = new Map<string, GameInfo>()\n let viteRoot: string\n\n return {\n name: \"puzzmo-simulator\",\n apply: \"serve\",\n\n configResolved(config: ResolvedConfig) {\n viteRoot = config.root\n games = discoverGames(viteRoot)\n\n if (games.size === 0) {\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m\\x1b[2m no puzzmo.json files found\\x1b[22m`)\n } else {\n const names = [...games.values()].map((g) => `\\x1b[36m${g.slug}\\x1b[39m`)\n const label = games.size === 1 ? \"game\" : \"games\"\n config.logger.info(`\\x1b[33m\\x1b[1m PUZZMO \\x1b[22m\\x1b[39m found ${games.size} ${label}: ${names.join(\"\\x1b[2m, \\x1b[22m\")}`)\n }\n },\n\n resolveId(id) {\n if (id === virtualID || id.startsWith(virtualID + \"?\")) return \"\\0\" + id\n },\n\n load(id) {\n if (!id.startsWith(\"\\0\" + virtualID)) return\n const params = new URLSearchParams(id.split(\"?\")[1] || \"\")\n const gameSlug = params.get(\"game\")\n const game = gameSlug ? games.get(gameSlug) : games.size === 1 ? games.values().next().value : undefined\n return generateSimulatorCode(options, game)\n },\n\n configureServer(server) {\n server.middlewares.use(\"/oauth/callback\", (_req, res) => {\n res.setHeader(\"Content-Type\", \"text/html\")\n res.end(`<!DOCTYPE html>\n<html><head><title>Puzzmo OAuth</title></head>\n<body><script>\nvar params = new URLSearchParams(window.location.search);\nvar returnUrl = sessionStorage.getItem(\"oauth_return_url\") || \"/\";\nvar url = new URL(returnUrl);\nparams.forEach(function(v, k) { url.searchParams.set(k, v); });\nwindow.location.href = url.toString();\n</script></body></html>`)\n })\n\n // Serve the simulator init module, resolving the game from the referer\n server.middlewares.use(async (req, res, next) => {\n if (req.url?.split(\"?\")[0] !== simulatorURL) return next()\n\n const game = resolveGameFromReferer(req.headers.referer, games, viteRoot)\n const moduleID = virtualID + (game ? `?game=${game.slug}` : \"\")\n const result = await server.transformRequest(moduleID)\n if (!result) return next()\n res.setHeader(\"Content-Type\", \"application/javascript\")\n res.end(result.code)\n })\n },\n\n transformIndexHtml() {\n return [\n {\n tag: \"script\",\n attrs: { type: \"module\", src: simulatorURL },\n injectTo: \"head\",\n },\n ]\n },\n }\n}\n\ntype BundlePluginOptions = {\n /** Entry file for the bundle */\n entry: string\n /** Output file name */\n outputFile: string\n}\n\nfunction createBundlePlugin(pluginName: string, defaults: BundlePluginOptions) {\n return (options: Partial<BundlePluginOptions> = {}): Plugin => {\n const { entry, outputFile } = { ...defaults, ...options }\n return {\n name: pluginName,\n apply: \"build\",\n async closeBundle() {\n // If the caller overrode `entry`, honor it as-is. Otherwise try `.js` first, then `.ts`.\n const resolvedEntry = options.entry\n ? path.isAbsolute(entry)\n ? entry\n : path.resolve(process.cwd(), entry)\n : (resolveBundleEntry(process.cwd(), stripBundleExt(entry)) ?? path.resolve(process.cwd(), entry))\n try {\n await build({\n configFile: false,\n logLevel: \"warn\",\n build: {\n lib: {\n entry: resolvedEntry,\n formats: [\"es\"],\n fileName: () => outputFile,\n },\n outDir: \"dist\",\n emptyOutDir: false,\n },\n })\n } catch (error) {\n console.error(`[${pluginName}] build failed:`, error)\n throw error\n }\n },\n }\n }\n}\n\n/** Strip the trailing extension from a default entry path so we can probe siblings. */\nconst stripBundleExt = (p: string) => p.replace(/\\.[jt]sx?$/i, \"\")\n\n/** Returns the absolute path to the first matching extension under `dir`, or null. */\nconst resolveBundleEntry = (dir: string, baseRelative: string): string | null => {\n for (const ext of [\".js\", \".ts\"]) {\n const candidate = path.join(dir, baseRelative + ext)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nexport type AppBundlePluginOptions = Partial<BundlePluginOptions>\n\n/**\n * Vite plugin that produces dist/app-bundle.js after the main build for app-level integrations.\n *\n * The bundle exports `renderThumbnail(puzzleStr, inputStr?, config?)` — a pure\n * SVG-string renderer used by the Puzzmo platform for puzzle previews.\n */\nexport const appBundlePlugin = createBundlePlugin(\"app-bundle\", { entry: \"src/appBundle.js\", outputFile: \"app-bundle.js\" })\n\nexport type EditorBundlePluginOptions = Partial<BundlePluginOptions>\n\n/** Vite plugin that produces dist/editor-bundle.js after the main build for editor-level integrations. */\nexport const editorBundlePlugin = createBundlePlugin(\"editor-bundle\", { entry: \"src/editorBundle.js\", outputFile: \"editor-bundle.js\" })\n\n/**\n * Recursively find directories containing puzzmo.json, up to `maxDepth` levels deep.\n *\n * @internal\n */\nexport const findPuzzmoJsonDirs = (root: string, maxDepth: number, depth = 0): string[] => {\n if (depth >= maxDepth) return []\n const results: string[] = []\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(root, { withFileTypes: true })\n } catch {\n return results\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue\n const dir = path.join(root, entry.name)\n if (fs.existsSync(path.join(dir, \"puzzmo.json\"))) {\n results.push(dir)\n }\n results.push(...findPuzzmoJsonDirs(dir, maxDepth, depth + 1))\n }\n return results\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@puzzmo/sdk",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "description": "Puzzmo runtime SDK for game developers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",