@epic-web/workshop-utils 6.40.2 → 6.41.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.
@@ -294,7 +294,6 @@ async function getQueue() {
294
294
  return _queue;
295
295
  _queue = new PQueue({
296
296
  concurrency: 1,
297
- throwOnTimeout: true,
298
297
  timeout: 1000 * 60,
299
298
  });
300
299
  return _queue;
@@ -1 +1 @@
1
- {"version":3,"file":"compile-mdx.server.js","sourceRoot":"","sources":["../../src/compile-mdx.server.ts"],"names":[],"mappings":"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","sourcesContent":["import './init-env.js'\n\nimport fs from 'fs'\nimport path from 'path'\nimport { rehypeCodeBlocksShiki } from '@kentcdodds/md-temp'\nimport { type Element, type Root as HastRoot } from 'hast'\nimport lz from 'lz-string'\nimport md5 from 'md5-hex'\nimport { type Root as MdastRoot, type PhrasingContent } from 'mdast'\nimport { type MdxJsxFlowElement } from 'mdast-util-mdx-jsx'\nimport { bundleMDX } from 'mdx-bundler'\nimport PQueue from 'p-queue'\nimport rehypeAutolinkHeadings from 'rehype-autolink-headings'\nimport emoji from 'remark-emoji'\nimport gfm from 'remark-gfm'\nimport { type PluggableList } from 'unified'\nimport { visit } from 'unist-util-visit'\nimport {\n\tcachified,\n\tcompiledInstructionMarkdownCache,\n\tcompiledMarkdownCache,\n\tshouldForceFresh,\n} from './cache.server.js'\nimport { type Timings } from './timing.server.js'\nimport { checkConnection } from './utils.server.js'\n\nfunction remarkMermaidCodeToSvg() {\n\treturn async (tree: MdastRoot) => {\n\t\tconst promises: Array<Promise<void>> = []\n\t\tvisit(tree, 'code', (node, index, parent) => {\n\t\t\tif (node.lang === 'mermaid' && parent && typeof index === 'number') {\n\t\t\t\tconst promise = (async () => {\n\t\t\t\t\tconst isConnected = await checkConnection()\n\t\t\t\t\tif (isConnected) {\n\t\t\t\t\t\tconst compressed = lz.compressToEncodedURIComponent(node.value)\n\t\t\t\t\t\tconst url = `https://mermaid-to-svg.kentcdodds.workers.dev/svg?mermaid=${compressed}`\n\n\t\t\t\t\t\tconst timeout = AbortSignal.timeout(5000)\n\t\t\t\t\t\tconst svgResponse = await fetch(url, { signal: timeout }).catch(\n\t\t\t\t\t\t\t() => null,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (svgResponse?.ok) {\n\t\t\t\t\t\t\tconst svgText = await svgResponse.text()\n\t\t\t\t\t\t\tif (svgText) {\n\t\t\t\t\t\t\t\tparent.children[index] = {\n\t\t\t\t\t\t\t\t\ttype: 'mdxJsxFlowElement',\n\t\t\t\t\t\t\t\t\tname: 'div',\n\t\t\t\t\t\t\t\t\tattributes: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\t\t\t\t\t\t\tname: 'className',\n\t\t\t\t\t\t\t\t\t\t\tvalue: 'mermaid not-prose',\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\t\t\t\t\t\t\tname: 'dangerouslySetInnerHTML',\n\t\t\t\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'mdxJsxAttributeValueExpression',\n\t\t\t\t\t\t\t\t\t\t\t\tvalue: `{__html: ${JSON.stringify(svgText)}}`,\n\t\t\t\t\t\t\t\t\t\t\t\t// This hack brought to you by this: https://github.com/syntax-tree/hast-util-to-estree/blob/e5ccb97e9f42bba90359ea6d0f83a11d74e0dad6/lib/handlers/mdx-expression.js#L35-L38\n\t\t\t\t\t\t\t\t\t\t\t\t// no idea why we're required to have estree here, but I'm pretty sure someone is supposed to add it automatically for us and it just never happens...\n\t\t\t\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\t\t\t\testree: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Program',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsourceType: 'script',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbody: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'ExpressionStatement',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texpression: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'ObjectExpression',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tshorthand: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcomputed: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkind: 'init',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname: '__html',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: svgText,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tchildren: [],\n\t\t\t\t\t\t\t\t} satisfies MdxJsxFlowElement\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tparent.children[index] = {\n\t\t\t\t\t\ttype: 'mdxJsxFlowElement',\n\t\t\t\t\t\tname: 'Mermaid',\n\t\t\t\t\t\tattributes: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\t\t\t\tname: 'code',\n\t\t\t\t\t\t\t\tvalue: node.value,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tchildren: [],\n\t\t\t\t\t} satisfies MdxJsxFlowElement\n\t\t\t\t})()\n\t\t\t\tpromises.push(promise)\n\t\t\t}\n\t\t})\n\t\tawait Promise.all(promises)\n\t}\n}\n\nfunction trimCodeBlocks() {\n\treturn async function transformer(tree: HastRoot) {\n\t\tvisit(tree, 'element', (preNode: Element) => {\n\t\t\tif (preNode.tagName !== 'pre' || !preNode.children.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst codeNode = preNode.children[0]\n\t\t\tif (\n\t\t\t\t!codeNode ||\n\t\t\t\tcodeNode.type !== 'element' ||\n\t\t\t\tcodeNode.tagName !== 'code'\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [codeStringNode] = codeNode.children\n\t\t\tif (!codeStringNode) return\n\n\t\t\tif (codeStringNode.type !== 'text') {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`trimCodeBlocks: Unexpected: codeStringNode type is not \"text\": ${codeStringNode.type}`,\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcodeStringNode.value = codeStringNode.value.trimEnd()\n\t\t})\n\t}\n}\n\nfunction removePreContainerDivs() {\n\treturn async function preContainerDivsTransformer(tree: HastRoot) {\n\t\tvisit(\n\t\t\ttree,\n\t\t\t{ type: 'element', tagName: 'pre' },\n\t\t\tfunction visitor(node, index, parent) {\n\t\t\t\tif (parent?.type !== 'element') return\n\t\t\t\tif (parent.tagName !== 'div') return\n\t\t\t\tif (parent.children.length !== 1 && index === 0) return\n\t\t\t\tObject.assign(parent, node)\n\t\t\t},\n\t\t)\n\t}\n}\n\nconst rehypePlugins = [\n\t[rehypeAutolinkHeadings, { behavior: 'wrap' }],\n\ttrimCodeBlocks,\n\trehypeCodeBlocksShiki,\n\tremovePreContainerDivs,\n] satisfies PluggableList\n\nconst verboseLog =\n\tprocess.env.EPICSHOP_VERBOSE_LOG === 'true' ? console.log : () => {}\n\nexport async function compileMdx(\n\tfile: string,\n\t{\n\t\trequest,\n\t\ttimings,\n\t\tforceFresh,\n\t}: {\n\t\trequest?: Request\n\t\ttimings?: Timings\n\t\tforceFresh?: boolean\n\t} = {},\n) {\n\tconst stat = await fs.promises\n\t\t.stat(file)\n\t\t.catch((error: unknown) => ({ error }))\n\tif ('error' in stat) {\n\t\tthrow new Error(`File stat cannot be read: ${stat.error}`)\n\t}\n\n\tconst key = `file:${file}`\n\tforceFresh = await shouldForceFresh({ forceFresh, request, key })\n\n\tconst existingCacheEntry = await compiledInstructionMarkdownCache.get(key)\n\tif (!forceFresh && existingCacheEntry) {\n\t\tforceFresh = stat.mtimeMs > existingCacheEntry.metadata.createdTime\n\t}\n\n\treturn cachified({\n\t\tkey,\n\t\tcache: compiledInstructionMarkdownCache,\n\t\trequest,\n\t\ttimings,\n\t\tforceFresh,\n\t\tgetFreshValue: () => compileMdxImpl(file),\n\t})\n}\n\nasync function compileMdxImpl(file: string): Promise<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}> {\n\tlet title: string | null = null\n\tconst epicVideoEmbeds: Array<string> = []\n\n\ttry {\n\t\tverboseLog(`Compiling ${file}`)\n\t\tconst bundleResult = await queuedBundleMDX({\n\t\t\tfile,\n\t\t\tcwd: path.dirname(file),\n\t\t\tmdxOptions(options) {\n\t\t\t\toptions.remarkPlugins = [\n\t\t\t\t\t...(options.remarkPlugins ?? []),\n\t\t\t\t\tgfm,\n\t\t\t\t\tremarkMermaidCodeToSvg,\n\t\t\t\t\t() => (tree: MdastRoot) => {\n\t\t\t\t\t\tvisit(tree, 'heading', (node) => {\n\t\t\t\t\t\t\tif (title) return\n\t\t\t\t\t\t\tif (node.depth === 1) {\n\t\t\t\t\t\t\t\t// Extract plain text content, preserving inline code but stripping other formatting\n\t\t\t\t\t\t\t\tconst extractText = (nodes: Array<PhrasingContent>): string => {\n\t\t\t\t\t\t\t\t\treturn nodes\n\t\t\t\t\t\t\t\t\t\t.map((childNode: PhrasingContent) => {\n\t\t\t\t\t\t\t\t\t\t\tif (childNode.type === 'text') {\n\t\t\t\t\t\t\t\t\t\t\t\treturn childNode.value\n\t\t\t\t\t\t\t\t\t\t\t} else if (childNode.type === 'inlineCode') {\n\t\t\t\t\t\t\t\t\t\t\t\treturn `\\`${childNode.value}\\``\n\t\t\t\t\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\t\t\t\t\tchildNode.type === 'strong' ||\n\t\t\t\t\t\t\t\t\t\t\t\tchildNode.type === 'emphasis'\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t// For formatting like bold/italic, just extract the text content\n\t\t\t\t\t\t\t\t\t\t\t\treturn extractText(childNode.children || [])\n\t\t\t\t\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\t\t\t\t\t'children' in childNode &&\n\t\t\t\t\t\t\t\t\t\t\t\tchildNode.children\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t// For other nodes with children, recursively extract text\n\t\t\t\t\t\t\t\t\t\t\t\treturn extractText(childNode.children || [])\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\treturn ''\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.join('')\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttitle = extractText(node.children || []).trim()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\ttitle = title ? title.replace(/^\\d+\\. /, '').trim() : null\n\t\t\t\t\t},\n\t\t\t\t\t() => (tree: MdastRoot) => {\n\t\t\t\t\t\tvisit(tree, 'mdxJsxFlowElement', (jsxEl) => {\n\t\t\t\t\t\t\tif (jsxEl.name !== 'EpicVideo') return\n\t\t\t\t\t\t\tconst urlAttr = jsxEl.attributes.find(\n\t\t\t\t\t\t\t\t(a) => a.type === 'mdxJsxAttribute' && a.name === 'url',\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (!urlAttr) return\n\t\t\t\t\t\t\tlet url = urlAttr.value\n\t\t\t\t\t\t\tif (typeof url !== 'string') return\n\t\t\t\t\t\t\tif (url.endsWith('/')) url = url.slice(0, -1)\n\t\t\t\t\t\t\tepicVideoEmbeds.push(url)\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t\temoji,\n\t\t\t\t]\n\t\t\t\toptions.rehypePlugins = [\n\t\t\t\t\t...(options.rehypePlugins ?? []),\n\t\t\t\t\t...rehypePlugins,\n\t\t\t\t]\n\t\t\t\toptions.mdxExtensions = ['.mdx', '.md']\n\t\t\t\toptions.format = 'mdx'\n\t\t\t\toptions.development = false\n\t\t\t\treturn options\n\t\t\t},\n\t\t})\n\t\tif (!bundleResult) throw new Error(`Timeout for file: ${file}`)\n\n\t\tconst result = { code: bundleResult.code, title, epicVideoEmbeds }\n\t\treturn result\n\t} catch (error: unknown) {\n\t\tconsole.error(`Compilation error for file: `, file, error)\n\t\tthrow error\n\t} finally {\n\t\tverboseLog(`Successfully compiled ${file}`)\n\t}\n}\n\nexport async function compileMarkdownString(markdownString: string) {\n\treturn cachified({\n\t\tkey: md5(markdownString),\n\t\tcache: compiledMarkdownCache,\n\t\tttl: 1000 * 60 * 60 * 24,\n\t\tgetFreshValue: async () => {\n\t\t\ttry {\n\t\t\t\tverboseLog(`Compiling string`, markdownString)\n\t\t\t\tconst result = await queuedBundleMDX({\n\t\t\t\t\tsource: markdownString,\n\t\t\t\t\tmdxOptions(options) {\n\t\t\t\t\t\toptions.rehypePlugins = [\n\t\t\t\t\t\t\t...(options.rehypePlugins ?? []),\n\t\t\t\t\t\t\t...rehypePlugins,\n\t\t\t\t\t\t]\n\t\t\t\t\t\toptions.development = false\n\t\t\t\t\t\treturn options\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tif (!result) throw new Error(`Timed out compiling markdown string`)\n\n\t\t\t\treturn result.code\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconsole.error(`Compilation error for code: `, markdownString, error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tverboseLog(`Successfully compiled string`, markdownString)\n\t\t\t}\n\t\t},\n\t})\n}\n\nlet _queue: PQueue | null = null\nasync function getQueue() {\n\tif (_queue) return _queue\n\n\t_queue = new PQueue({\n\t\tconcurrency: 1,\n\t\tthrowOnTimeout: true,\n\t\ttimeout: 1000 * 60,\n\t})\n\treturn _queue\n}\n\n// We have to use a queue because we can't run more than one of these at a time\n// or we'll hit an out of memory error because esbuild uses a lot of memory...\nasync function queuedBundleMDX(...args: Parameters<typeof bundleMDX>) {\n\tconst queue = await getQueue()\n\tconst result = await queue.add(() => bundleMDX(...args))\n\treturn result\n}\n"]}
1
+ {"version":3,"file":"compile-mdx.server.js","sourceRoot":"","sources":["../../src/compile-mdx.server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,EAAE,MAAM,WAAW,CAAA;AAC1B,OAAO,GAAG,MAAM,SAAS,CAAA;AAGzB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,MAAM,MAAM,SAAS,CAAA;AAC5B,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,MAAM,cAAc,CAAA;AAChC,OAAO,GAAG,MAAM,YAAY,CAAA;AAE5B,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EACN,SAAS,EACT,gCAAgC,EAChC,qBAAqB,EACrB,gBAAgB,GAChB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEnD,SAAS,sBAAsB;IAC9B,OAAO,KAAK,EAAE,IAAe,EAAE,EAAE;QAChC,MAAM,QAAQ,GAAyB,EAAE,CAAA;QACzC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACpE,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;oBAC3B,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAA;oBAC3C,IAAI,WAAW,EAAE,CAAC;wBACjB,MAAM,UAAU,GAAG,EAAE,CAAC,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;wBAC/D,MAAM,GAAG,GAAG,6DAA6D,UAAU,EAAE,CAAA;wBAErF,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;wBACzC,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAC9D,GAAG,EAAE,CAAC,IAAI,CACV,CAAA;wBACD,IAAI,WAAW,EAAE,EAAE,EAAE,CAAC;4BACrB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAA;4BACxC,IAAI,OAAO,EAAE,CAAC;gCACb,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG;oCACxB,IAAI,EAAE,mBAAmB;oCACzB,IAAI,EAAE,KAAK;oCACX,UAAU,EAAE;wCACX;4CACC,IAAI,EAAE,iBAAiB;4CACvB,IAAI,EAAE,WAAW;4CACjB,KAAK,EAAE,mBAAmB;yCAC1B;wCACD;4CACC,IAAI,EAAE,iBAAiB;4CACvB,IAAI,EAAE,yBAAyB;4CAC/B,KAAK,EAAE;gDACN,IAAI,EAAE,gCAAgC;gDACtC,KAAK,EAAE,YAAY,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG;gDAC7C,4KAA4K;gDAC5K,sJAAsJ;gDACtJ,IAAI,EAAE;oDACL,MAAM,EAAE;wDACP,IAAI,EAAE,SAAS;wDACf,UAAU,EAAE,QAAQ;wDACpB,IAAI,EAAE;4DACL;gEACC,IAAI,EAAE,qBAAqB;gEAC3B,UAAU,EAAE;oEACX,IAAI,EAAE,kBAAkB;oEACxB,UAAU,EAAE;wEACX;4EACC,IAAI,EAAE,UAAU;4EAChB,MAAM,EAAE,KAAK;4EACb,SAAS,EAAE,KAAK;4EAChB,QAAQ,EAAE,KAAK;4EACf,IAAI,EAAE,MAAM;4EACZ,GAAG,EAAE;gFACJ,IAAI,EAAE,YAAY;gFAClB,IAAI,EAAE,QAAQ;6EACd;4EACD,KAAK,EAAE;gFACN,IAAI,EAAE,SAAS;gFACf,KAAK,EAAE,OAAO;6EACd;yEACD;qEACD;iEACD;6DACD;yDACD;qDACD;iDACD;6CACD;yCACD;qCACD;oCACD,QAAQ,EAAE,EAAE;iCACgB,CAAA;gCAC7B,OAAM;4BACP,CAAC;wBACF,CAAC;oBACF,CAAC;oBAED,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG;wBACxB,IAAI,EAAE,mBAAmB;wBACzB,IAAI,EAAE,SAAS;wBACf,UAAU,EAAE;4BACX;gCACC,IAAI,EAAE,iBAAiB;gCACvB,IAAI,EAAE,MAAM;gCACZ,KAAK,EAAE,IAAI,CAAC,KAAK;6BACjB;yBACD;wBACD,QAAQ,EAAE,EAAE;qBACgB,CAAA;gBAC9B,CAAC,CAAC,EAAE,CAAA;gBACJ,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACvB,CAAC;QACF,CAAC,CAAC,CAAA;QACF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC5B,CAAC,CAAA;AACF,CAAC;AAED,SAAS,cAAc;IACtB,OAAO,KAAK,UAAU,WAAW,CAAC,IAAc;QAC/C,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE;YAC3C,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC3D,OAAM;YACP,CAAC;YACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YACpC,IACC,CAAC,QAAQ;gBACT,QAAQ,CAAC,IAAI,KAAK,SAAS;gBAC3B,QAAQ,CAAC,OAAO,KAAK,MAAM,EAC1B,CAAC;gBACF,OAAM;YACP,CAAC;YACD,MAAM,CAAC,cAAc,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAA;YAC1C,IAAI,CAAC,cAAc;gBAAE,OAAM;YAE3B,IAAI,cAAc,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpC,OAAO,CAAC,IAAI,CACX,kEAAkE,cAAc,CAAC,IAAI,EAAE,CACvF,CAAA;gBACD,OAAM;YACP,CAAC;YACD,cAAc,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,CAAA;QACtD,CAAC,CAAC,CAAA;IACH,CAAC,CAAA;AACF,CAAC;AAED,SAAS,sBAAsB;IAC9B,OAAO,KAAK,UAAU,2BAA2B,CAAC,IAAc;QAC/D,KAAK,CACJ,IAAI,EACJ,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,EACnC,SAAS,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM;YACnC,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS;gBAAE,OAAM;YACtC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK;gBAAE,OAAM;YACpC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAM;YACvD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAC5B,CAAC,CACD,CAAA;IACF,CAAC,CAAA;AACF,CAAC;AAED,MAAM,aAAa,GAAG;IACrB,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC9C,cAAc;IACd,qBAAqB;IACrB,sBAAsB;CACE,CAAA;AAEzB,MAAM,UAAU,GACf,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAErE,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,IAAY,EACZ,EACC,OAAO,EACP,OAAO,EACP,UAAU,MAKP,EAAE;IAEN,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ;SAC5B,IAAI,CAAC,IAAI,CAAC;SACV,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACxC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;IAC3D,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,IAAI,EAAE,CAAA;IAC1B,UAAU,GAAG,MAAM,gBAAgB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;IAEjE,MAAM,kBAAkB,GAAG,MAAM,gCAAgC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1E,IAAI,CAAC,UAAU,IAAI,kBAAkB,EAAE,CAAC;QACvC,UAAU,GAAG,IAAI,CAAC,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAA;IACpE,CAAC;IAED,OAAO,SAAS,CAAC;QAChB,GAAG;QACH,KAAK,EAAE,gCAAgC;QACvC,OAAO;QACP,OAAO;QACP,UAAU;QACV,aAAa,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC;KACzC,CAAC,CAAA;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAY;IAKzC,IAAI,KAAK,GAAkB,IAAI,CAAA;IAC/B,MAAM,eAAe,GAAkB,EAAE,CAAA;IAEzC,IAAI,CAAC;QACJ,UAAU,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;QAC/B,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;YAC1C,IAAI;YACJ,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACvB,UAAU,CAAC,OAAO;gBACjB,OAAO,CAAC,aAAa,GAAG;oBACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;oBAChC,GAAG;oBACH,sBAAsB;oBACtB,GAAG,EAAE,CAAC,CAAC,IAAe,EAAE,EAAE;wBACzB,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;4BAC/B,IAAI,KAAK;gCAAE,OAAM;4BACjB,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gCACtB,oFAAoF;gCACpF,MAAM,WAAW,GAAG,CAAC,KAA6B,EAAU,EAAE;oCAC7D,OAAO,KAAK;yCACV,GAAG,CAAC,CAAC,SAA0B,EAAE,EAAE;wCACnC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;4CAC/B,OAAO,SAAS,CAAC,KAAK,CAAA;wCACvB,CAAC;6CAAM,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;4CAC5C,OAAO,KAAK,SAAS,CAAC,KAAK,IAAI,CAAA;wCAChC,CAAC;6CAAM,IACN,SAAS,CAAC,IAAI,KAAK,QAAQ;4CAC3B,SAAS,CAAC,IAAI,KAAK,UAAU,EAC5B,CAAC;4CACF,iEAAiE;4CACjE,OAAO,WAAW,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;wCAC7C,CAAC;6CAAM,IACN,UAAU,IAAI,SAAS;4CACvB,SAAS,CAAC,QAAQ,EACjB,CAAC;4CACF,0DAA0D;4CAC1D,OAAO,WAAW,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;wCAC7C,CAAC;wCACD,OAAO,EAAE,CAAA;oCACV,CAAC,CAAC;yCACD,IAAI,CAAC,EAAE,CAAC,CAAA;gCACX,CAAC,CAAA;gCAED,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;4BAChD,CAAC;wBACF,CAAC,CAAC,CAAA;wBACF,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;oBAC3D,CAAC;oBACD,GAAG,EAAE,CAAC,CAAC,IAAe,EAAE,EAAE;wBACzB,KAAK,CAAC,IAAI,EAAE,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;4BAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gCAAE,OAAM;4BACtC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CACvD,CAAA;4BACD,IAAI,CAAC,OAAO;gCAAE,OAAM;4BACpB,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAA;4BACvB,IAAI,OAAO,GAAG,KAAK,QAAQ;gCAAE,OAAM;4BACnC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;gCAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;4BAC7C,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;wBAC1B,CAAC,CAAC,CAAA;oBACH,CAAC;oBACD,KAAK;iBACL,CAAA;gBACD,OAAO,CAAC,aAAa,GAAG;oBACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;oBAChC,GAAG,aAAa;iBAChB,CAAA;gBACD,OAAO,CAAC,aAAa,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;gBACvC,OAAO,CAAC,MAAM,GAAG,KAAK,CAAA;gBACtB,OAAO,CAAC,WAAW,GAAG,KAAK,CAAA;gBAC3B,OAAO,OAAO,CAAA;YACf,CAAC;SACD,CAAC,CAAA;QACF,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAA;QAE/D,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,eAAe,EAAE,CAAA;QAClE,OAAO,MAAM,CAAA;IACd,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAC1D,MAAM,KAAK,CAAA;IACZ,CAAC;YAAS,CAAC;QACV,UAAU,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAA;IAC5C,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,cAAsB;IACjE,OAAO,SAAS,CAAC;QAChB,GAAG,EAAE,GAAG,CAAC,cAAc,CAAC;QACxB,KAAK,EAAE,qBAAqB;QAC5B,GAAG,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACxB,aAAa,EAAE,KAAK,IAAI,EAAE;YACzB,IAAI,CAAC;gBACJ,UAAU,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAA;gBAC9C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;oBACpC,MAAM,EAAE,cAAc;oBACtB,UAAU,CAAC,OAAO;wBACjB,OAAO,CAAC,aAAa,GAAG;4BACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;4BAChC,GAAG,aAAa;yBAChB,CAAA;wBACD,OAAO,CAAC,WAAW,GAAG,KAAK,CAAA;wBAC3B,OAAO,OAAO,CAAA;oBACf,CAAC;iBACD,CAAC,CAAA;gBACF,IAAI,CAAC,MAAM;oBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;gBAEnE,OAAO,MAAM,CAAC,IAAI,CAAA;YACnB,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,cAAc,EAAE,KAAK,CAAC,CAAA;gBACpE,MAAM,KAAK,CAAA;YACZ,CAAC;oBAAS,CAAC;gBACV,UAAU,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAA;YAC3D,CAAC;QACF,CAAC;KACD,CAAC,CAAA;AACH,CAAC;AAED,IAAI,MAAM,GAAkB,IAAI,CAAA;AAChC,KAAK,UAAU,QAAQ;IACtB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,MAAM,GAAG,IAAI,MAAM,CAAC;QACnB,WAAW,EAAE,CAAC;QACd,OAAO,EAAE,IAAI,GAAG,EAAE;KAClB,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACd,CAAC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,KAAK,UAAU,eAAe,CAAC,GAAG,IAAkC;IACnE,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAA;IAC9B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;IACxD,OAAO,MAAM,CAAA;AACd,CAAC","sourcesContent":["import './init-env.js'\n\nimport fs from 'fs'\nimport path from 'path'\nimport { rehypeCodeBlocksShiki } from '@kentcdodds/md-temp'\nimport { type Element, type Root as HastRoot } from 'hast'\nimport lz from 'lz-string'\nimport md5 from 'md5-hex'\nimport { type Root as MdastRoot, type PhrasingContent } from 'mdast'\nimport { type MdxJsxFlowElement } from 'mdast-util-mdx-jsx'\nimport { bundleMDX } from 'mdx-bundler'\nimport PQueue from 'p-queue'\nimport rehypeAutolinkHeadings from 'rehype-autolink-headings'\nimport emoji from 'remark-emoji'\nimport gfm from 'remark-gfm'\nimport { type PluggableList } from 'unified'\nimport { visit } from 'unist-util-visit'\nimport {\n\tcachified,\n\tcompiledInstructionMarkdownCache,\n\tcompiledMarkdownCache,\n\tshouldForceFresh,\n} from './cache.server.js'\nimport { type Timings } from './timing.server.js'\nimport { checkConnection } from './utils.server.js'\n\nfunction remarkMermaidCodeToSvg() {\n\treturn async (tree: MdastRoot) => {\n\t\tconst promises: Array<Promise<void>> = []\n\t\tvisit(tree, 'code', (node, index, parent) => {\n\t\t\tif (node.lang === 'mermaid' && parent && typeof index === 'number') {\n\t\t\t\tconst promise = (async () => {\n\t\t\t\t\tconst isConnected = await checkConnection()\n\t\t\t\t\tif (isConnected) {\n\t\t\t\t\t\tconst compressed = lz.compressToEncodedURIComponent(node.value)\n\t\t\t\t\t\tconst url = `https://mermaid-to-svg.kentcdodds.workers.dev/svg?mermaid=${compressed}`\n\n\t\t\t\t\t\tconst timeout = AbortSignal.timeout(5000)\n\t\t\t\t\t\tconst svgResponse = await fetch(url, { signal: timeout }).catch(\n\t\t\t\t\t\t\t() => null,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (svgResponse?.ok) {\n\t\t\t\t\t\t\tconst svgText = await svgResponse.text()\n\t\t\t\t\t\t\tif (svgText) {\n\t\t\t\t\t\t\t\tparent.children[index] = {\n\t\t\t\t\t\t\t\t\ttype: 'mdxJsxFlowElement',\n\t\t\t\t\t\t\t\t\tname: 'div',\n\t\t\t\t\t\t\t\t\tattributes: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\t\t\t\t\t\t\tname: 'className',\n\t\t\t\t\t\t\t\t\t\t\tvalue: 'mermaid not-prose',\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\t\t\t\t\t\t\tname: 'dangerouslySetInnerHTML',\n\t\t\t\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'mdxJsxAttributeValueExpression',\n\t\t\t\t\t\t\t\t\t\t\t\tvalue: `{__html: ${JSON.stringify(svgText)}}`,\n\t\t\t\t\t\t\t\t\t\t\t\t// This hack brought to you by this: https://github.com/syntax-tree/hast-util-to-estree/blob/e5ccb97e9f42bba90359ea6d0f83a11d74e0dad6/lib/handlers/mdx-expression.js#L35-L38\n\t\t\t\t\t\t\t\t\t\t\t\t// no idea why we're required to have estree here, but I'm pretty sure someone is supposed to add it automatically for us and it just never happens...\n\t\t\t\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\t\t\t\testree: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Program',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsourceType: 'script',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbody: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'ExpressionStatement',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texpression: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'ObjectExpression',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tshorthand: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcomputed: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkind: 'init',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname: '__html',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: svgText,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tchildren: [],\n\t\t\t\t\t\t\t\t} satisfies MdxJsxFlowElement\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tparent.children[index] = {\n\t\t\t\t\t\ttype: 'mdxJsxFlowElement',\n\t\t\t\t\t\tname: 'Mermaid',\n\t\t\t\t\t\tattributes: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\t\t\t\tname: 'code',\n\t\t\t\t\t\t\t\tvalue: node.value,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tchildren: [],\n\t\t\t\t\t} satisfies MdxJsxFlowElement\n\t\t\t\t})()\n\t\t\t\tpromises.push(promise)\n\t\t\t}\n\t\t})\n\t\tawait Promise.all(promises)\n\t}\n}\n\nfunction trimCodeBlocks() {\n\treturn async function transformer(tree: HastRoot) {\n\t\tvisit(tree, 'element', (preNode: Element) => {\n\t\t\tif (preNode.tagName !== 'pre' || !preNode.children.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst codeNode = preNode.children[0]\n\t\t\tif (\n\t\t\t\t!codeNode ||\n\t\t\t\tcodeNode.type !== 'element' ||\n\t\t\t\tcodeNode.tagName !== 'code'\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [codeStringNode] = codeNode.children\n\t\t\tif (!codeStringNode) return\n\n\t\t\tif (codeStringNode.type !== 'text') {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`trimCodeBlocks: Unexpected: codeStringNode type is not \"text\": ${codeStringNode.type}`,\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcodeStringNode.value = codeStringNode.value.trimEnd()\n\t\t})\n\t}\n}\n\nfunction removePreContainerDivs() {\n\treturn async function preContainerDivsTransformer(tree: HastRoot) {\n\t\tvisit(\n\t\t\ttree,\n\t\t\t{ type: 'element', tagName: 'pre' },\n\t\t\tfunction visitor(node, index, parent) {\n\t\t\t\tif (parent?.type !== 'element') return\n\t\t\t\tif (parent.tagName !== 'div') return\n\t\t\t\tif (parent.children.length !== 1 && index === 0) return\n\t\t\t\tObject.assign(parent, node)\n\t\t\t},\n\t\t)\n\t}\n}\n\nconst rehypePlugins = [\n\t[rehypeAutolinkHeadings, { behavior: 'wrap' }],\n\ttrimCodeBlocks,\n\trehypeCodeBlocksShiki,\n\tremovePreContainerDivs,\n] satisfies PluggableList\n\nconst verboseLog =\n\tprocess.env.EPICSHOP_VERBOSE_LOG === 'true' ? console.log : () => {}\n\nexport async function compileMdx(\n\tfile: string,\n\t{\n\t\trequest,\n\t\ttimings,\n\t\tforceFresh,\n\t}: {\n\t\trequest?: Request\n\t\ttimings?: Timings\n\t\tforceFresh?: boolean\n\t} = {},\n) {\n\tconst stat = await fs.promises\n\t\t.stat(file)\n\t\t.catch((error: unknown) => ({ error }))\n\tif ('error' in stat) {\n\t\tthrow new Error(`File stat cannot be read: ${stat.error}`)\n\t}\n\n\tconst key = `file:${file}`\n\tforceFresh = await shouldForceFresh({ forceFresh, request, key })\n\n\tconst existingCacheEntry = await compiledInstructionMarkdownCache.get(key)\n\tif (!forceFresh && existingCacheEntry) {\n\t\tforceFresh = stat.mtimeMs > existingCacheEntry.metadata.createdTime\n\t}\n\n\treturn cachified({\n\t\tkey,\n\t\tcache: compiledInstructionMarkdownCache,\n\t\trequest,\n\t\ttimings,\n\t\tforceFresh,\n\t\tgetFreshValue: () => compileMdxImpl(file),\n\t})\n}\n\nasync function compileMdxImpl(file: string): Promise<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}> {\n\tlet title: string | null = null\n\tconst epicVideoEmbeds: Array<string> = []\n\n\ttry {\n\t\tverboseLog(`Compiling ${file}`)\n\t\tconst bundleResult = await queuedBundleMDX({\n\t\t\tfile,\n\t\t\tcwd: path.dirname(file),\n\t\t\tmdxOptions(options) {\n\t\t\t\toptions.remarkPlugins = [\n\t\t\t\t\t...(options.remarkPlugins ?? []),\n\t\t\t\t\tgfm,\n\t\t\t\t\tremarkMermaidCodeToSvg,\n\t\t\t\t\t() => (tree: MdastRoot) => {\n\t\t\t\t\t\tvisit(tree, 'heading', (node) => {\n\t\t\t\t\t\t\tif (title) return\n\t\t\t\t\t\t\tif (node.depth === 1) {\n\t\t\t\t\t\t\t\t// Extract plain text content, preserving inline code but stripping other formatting\n\t\t\t\t\t\t\t\tconst extractText = (nodes: Array<PhrasingContent>): string => {\n\t\t\t\t\t\t\t\t\treturn nodes\n\t\t\t\t\t\t\t\t\t\t.map((childNode: PhrasingContent) => {\n\t\t\t\t\t\t\t\t\t\t\tif (childNode.type === 'text') {\n\t\t\t\t\t\t\t\t\t\t\t\treturn childNode.value\n\t\t\t\t\t\t\t\t\t\t\t} else if (childNode.type === 'inlineCode') {\n\t\t\t\t\t\t\t\t\t\t\t\treturn `\\`${childNode.value}\\``\n\t\t\t\t\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\t\t\t\t\tchildNode.type === 'strong' ||\n\t\t\t\t\t\t\t\t\t\t\t\tchildNode.type === 'emphasis'\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t// For formatting like bold/italic, just extract the text content\n\t\t\t\t\t\t\t\t\t\t\t\treturn extractText(childNode.children || [])\n\t\t\t\t\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\t\t\t\t\t'children' in childNode &&\n\t\t\t\t\t\t\t\t\t\t\t\tchildNode.children\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t// For other nodes with children, recursively extract text\n\t\t\t\t\t\t\t\t\t\t\t\treturn extractText(childNode.children || [])\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\treturn ''\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.join('')\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttitle = extractText(node.children || []).trim()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\ttitle = title ? title.replace(/^\\d+\\. /, '').trim() : null\n\t\t\t\t\t},\n\t\t\t\t\t() => (tree: MdastRoot) => {\n\t\t\t\t\t\tvisit(tree, 'mdxJsxFlowElement', (jsxEl) => {\n\t\t\t\t\t\t\tif (jsxEl.name !== 'EpicVideo') return\n\t\t\t\t\t\t\tconst urlAttr = jsxEl.attributes.find(\n\t\t\t\t\t\t\t\t(a) => a.type === 'mdxJsxAttribute' && a.name === 'url',\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (!urlAttr) return\n\t\t\t\t\t\t\tlet url = urlAttr.value\n\t\t\t\t\t\t\tif (typeof url !== 'string') return\n\t\t\t\t\t\t\tif (url.endsWith('/')) url = url.slice(0, -1)\n\t\t\t\t\t\t\tepicVideoEmbeds.push(url)\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t\temoji,\n\t\t\t\t]\n\t\t\t\toptions.rehypePlugins = [\n\t\t\t\t\t...(options.rehypePlugins ?? []),\n\t\t\t\t\t...rehypePlugins,\n\t\t\t\t]\n\t\t\t\toptions.mdxExtensions = ['.mdx', '.md']\n\t\t\t\toptions.format = 'mdx'\n\t\t\t\toptions.development = false\n\t\t\t\treturn options\n\t\t\t},\n\t\t})\n\t\tif (!bundleResult) throw new Error(`Timeout for file: ${file}`)\n\n\t\tconst result = { code: bundleResult.code, title, epicVideoEmbeds }\n\t\treturn result\n\t} catch (error: unknown) {\n\t\tconsole.error(`Compilation error for file: `, file, error)\n\t\tthrow error\n\t} finally {\n\t\tverboseLog(`Successfully compiled ${file}`)\n\t}\n}\n\nexport async function compileMarkdownString(markdownString: string) {\n\treturn cachified({\n\t\tkey: md5(markdownString),\n\t\tcache: compiledMarkdownCache,\n\t\tttl: 1000 * 60 * 60 * 24,\n\t\tgetFreshValue: async () => {\n\t\t\ttry {\n\t\t\t\tverboseLog(`Compiling string`, markdownString)\n\t\t\t\tconst result = await queuedBundleMDX({\n\t\t\t\t\tsource: markdownString,\n\t\t\t\t\tmdxOptions(options) {\n\t\t\t\t\t\toptions.rehypePlugins = [\n\t\t\t\t\t\t\t...(options.rehypePlugins ?? []),\n\t\t\t\t\t\t\t...rehypePlugins,\n\t\t\t\t\t\t]\n\t\t\t\t\t\toptions.development = false\n\t\t\t\t\t\treturn options\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tif (!result) throw new Error(`Timed out compiling markdown string`)\n\n\t\t\t\treturn result.code\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconsole.error(`Compilation error for code: `, markdownString, error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tverboseLog(`Successfully compiled string`, markdownString)\n\t\t\t}\n\t\t},\n\t})\n}\n\nlet _queue: PQueue | null = null\nasync function getQueue() {\n\tif (_queue) return _queue\n\n\t_queue = new PQueue({\n\t\tconcurrency: 1,\n\t\ttimeout: 1000 * 60,\n\t})\n\treturn _queue\n}\n\n// We have to use a queue because we can't run more than one of these at a time\n// or we'll hit an out of memory error because esbuild uses a lot of memory...\nasync function queuedBundleMDX(...args: Parameters<typeof bundleMDX>) {\n\tconst queue = await getQueue()\n\tconst result = await queue.add(() => bundleMDX(...args))\n\treturn result\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import './init-env.js';
2
- import { createId as cuid } from '@paralleldrive/cuid2';
2
+ import { randomUUID as cuid } from 'crypto';
3
3
  import fsExtra from 'fs-extra';
4
4
  import { redirect } from 'react-router';
5
5
  import { z } from 'zod';
@@ -1 +1 @@
1
- {"version":3,"file":"db.server.js","sourceRoot":"","sources":["../../src/db.server.ts"],"names":[],"mappings":"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","sourcesContent":["import './init-env.js'\n\nimport { createId as cuid } from '@paralleldrive/cuid2'\nimport fsExtra from 'fs-extra'\nimport { redirect } from 'react-router'\nimport { z } from 'zod'\nimport { getWorkshopConfig } from './config.server.js'\nimport { saveJSON, loadJSON, migrateLegacyData } from './data-storage.server.js'\n\n// Attempt migration from legacy ~/.epicshop\nawait migrateLegacyData().catch(() => {})\n\nconst TokenSetSchema = z.object({\n\taccess_token: z.string(),\n\ttoken_type: z.string(),\n\tscope: z.string(),\n})\nexport const PlayerPreferencesSchema = z\n\t.object({\n\t\tminResolution: z.number().optional(),\n\t\tmaxResolution: z.number().optional(),\n\t\tvolumeRate: z.number().optional(),\n\t\tplaybackRate: z.number().optional(),\n\t\tautoplay: z.boolean().optional(),\n\t\tsubtitle: z\n\t\t\t.object({\n\t\t\t\tid: z.string().nullable().default(null),\n\t\t\t\tmode: z\n\t\t\t\t\t.literal('disabled')\n\t\t\t\t\t.or(z.literal('hidden'))\n\t\t\t\t\t.or(z.literal('showing'))\n\t\t\t\t\t.nullable()\n\t\t\t\t\t.default('disabled'),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.default({}),\n\t\tmuted: z.boolean().optional(),\n\t\ttheater: z.boolean().optional(),\n\t\tdefaultView: z.string().optional(),\n\t\tactiveSidebarTab: z.number().optional(),\n\t})\n\t.optional()\n\t.default({})\n\nconst PresencePreferencesSchema = z\n\t.object({\n\t\toptOut: z.boolean(),\n\t})\n\t.optional()\n\t.default({ optOut: false })\n\nconst AuthInfoSchema = z.object({\n\tid: z.string(),\n\ttokenSet: TokenSetSchema,\n\temail: z.string(),\n\tname: z.string().nullable().optional(),\n})\n\nconst MutedNotificationSchema = z.array(z.string()).default([])\n\nconst DataSchema = z.object({\n\tonboarding: z\n\t\t.object({\n\t\t\ttourVideosWatched: z.array(z.string()).default([]),\n\t\t})\n\t\t.passthrough()\n\t\t.optional()\n\t\t.default({ tourVideosWatched: [] }),\n\tpreferences: z\n\t\t.object({\n\t\t\tplayer: PlayerPreferencesSchema,\n\t\t\tpresence: PresencePreferencesSchema,\n\t\t\tplayground: z\n\t\t\t\t.object({\n\t\t\t\t\tpersist: z.boolean().default(false),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tfontSize: z.number().optional(),\n\t\t\texerciseWarning: z\n\t\t\t\t.object({\n\t\t\t\t\tdismissed: z.boolean().default(false),\n\t\t\t\t})\n\t\t\t\t.optional()\n\t\t\t\t.default({ dismissed: false }),\n\t\t})\n\t\t.optional()\n\t\t.default({}),\n\t// deprecated. Probably safe to remove in May 2026:\n\tauthInfo: AuthInfoSchema.optional(),\n\t// new:\n\tauthInfos: z.record(z.string(), AuthInfoSchema).optional(),\n\tclientId: z.string().optional(),\n\tmutedNotifications: MutedNotificationSchema.optional(),\n})\n\nexport async function getClientId() {\n\tconst data = await readDb()\n\tif (data?.clientId) return data.clientId\n\n\tconst clientId = cuid()\n\tawait saveJSON({ ...data, clientId })\n\treturn clientId\n}\n\nexport async function logout() {\n\tconst config = getWorkshopConfig()\n\tconst host = config.product.host\n\tif (host) {\n\t\tconst data = await readDb()\n\t\tconst newAuthInfos = { ...data?.authInfos }\n\t\tdelete newAuthInfos[host]\n\t\tawait saveJSON({\n\t\t\t...data,\n\t\t\tauthInfos: newAuthInfos,\n\t\t})\n\t}\n}\n\nexport async function deleteDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tconst { path: dbPath } = await loadJSON()\n\t\tif (dbPath && (await fsExtra.exists(dbPath))) {\n\t\t\tawait fsExtra.remove(dbPath)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(`Error deleting the database`, error)\n\t}\n}\n\nexport async function readDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\tconst maxRetries = 3\n\tconst baseDelay = 10\n\n\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\ttry {\n\t\t\tconst { data, path: dbPath } = await loadJSON()\n\t\t\tif (data && dbPath) {\n\t\t\t\tconst db = DataSchema.parse(data)\n\t\t\t\treturn db\n\t\t\t}\n\t\t\treturn null\n\t\t} catch (error) {\n\t\t\t// If this is a retry attempt, it might be a race condition\n\t\t\tif (attempt < maxRetries) {\n\t\t\t\tconst delay = baseDelay * Math.pow(2, attempt)\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Database read error on attempt ${attempt + 1}/${maxRetries + 1}, retrying in ${delay}ms...`,\n\t\t\t\t)\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay))\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Final attempt failed, handle as corrupted file\n\t\t\tconsole.error(\n\t\t\t\t`Error reading the database after ${attempt + 1} attempts, moving it to a .bkp file to avoid parsing errors in the future`,\n\t\t\t\terror,\n\t\t\t)\n\n\t\t\t// Log to Sentry if available\n\t\t\tif (process.env.SENTRY_DSN && process.env.EPICSHOP_IS_PUBLISHED) {\n\t\t\t\ttry {\n\t\t\t\t\tconst Sentry = await import('@sentry/react-router')\n\t\t\t\t\tSentry.captureException(error, {\n\t\t\t\t\t\ttags: {\n\t\t\t\t\t\t\terror_type: 'corrupted_database_file',\n\t\t\t\t\t\t\tretry_attempts: attempt.toString(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\textra: {\n\t\t\t\t\t\t\terrorMessage:\n\t\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\tretryAttempts: attempt,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t} catch (sentryError) {\n\t\t\t\t\tconsole.error('Failed to log to Sentry:', sentryError)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Try to move corrupted file to backup if we can determine the path\n\t\t\ttry {\n\t\t\t\tconst { path: dbPath } = await loadJSON()\n\t\t\t\tif (dbPath && (await fsExtra.exists(dbPath))) {\n\t\t\t\t\tvoid fsExtra.move(dbPath, `${dbPath}.bkp`).catch(() => {})\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\treturn null\n}\n\nexport async function getAuthInfo() {\n\tconst config = getWorkshopConfig()\n\tconst data = await readDb()\n\tif (config.product.host && typeof data?.authInfos === 'object') {\n\t\tif (config.product.host in data.authInfos) {\n\t\t\treturn data.authInfos[config.product.host]\n\t\t}\n\t}\n\n\t// special case for non-epicweb/epicreact workshops\n\tif (\n\t\t!config.product.host ||\n\t\tconfig.product.host === 'epicweb.dev' ||\n\t\tconfig.product.host === 'epicreact.dev'\n\t) {\n\t\t// upgrade from old authInfo to new authInfos\n\t\tif (data?.authInfo && config.product.host) {\n\t\t\tawait setAuthInfo(data.authInfo)\n\t\t}\n\t\treturn data?.authInfo ?? null\n\t}\n\n\treturn null\n}\n\nexport async function requireAuthInfo({\n\trequest,\n\tredirectTo,\n}: {\n\trequest: Request\n\tredirectTo?: string | null\n}) {\n\tconst authInfo = await getAuthInfo()\n\tif (!authInfo) {\n\t\tconst requestUrl = new URL(request.url)\n\t\tredirectTo =\n\t\t\tredirectTo === null\n\t\t\t\t? null\n\t\t\t\t: (redirectTo ?? `${requestUrl.pathname}${requestUrl.search}`)\n\t\tconst loginParams = redirectTo ? new URLSearchParams({ redirectTo }) : null\n\t\tconst loginRedirect = ['/login', loginParams?.toString()]\n\t\t\t.filter(Boolean)\n\t\t\t.join('?')\n\t\tthrow redirect(loginRedirect)\n\t}\n\treturn authInfo\n}\n\nexport async function setAuthInfo({\n\tid,\n\ttokenSet,\n\temail = 'unknown@example.com',\n\tname,\n}: {\n\tid: string\n\ttokenSet: Partial<z.infer<typeof TokenSetSchema>>\n\temail?: string | null\n\tname?: string | null\n}) {\n\tconst data = await readDb()\n\tconst authInfo = AuthInfoSchema.parse({ id, tokenSet, email, name })\n\tconst config = getWorkshopConfig()\n\tif (config.product.host) {\n\t\tawait saveJSON({\n\t\t\t...data,\n\t\t\tauthInfos: {\n\t\t\t\t...data?.authInfos,\n\t\t\t\t[config.product.host]: authInfo,\n\t\t\t},\n\t\t})\n\t} else {\n\t\tawait saveJSON({ ...data, authInfo })\n\t}\n\treturn authInfo\n}\n\nexport async function getPreferences() {\n\tconst data = await readDb()\n\treturn data?.preferences ?? null\n}\n\nexport async function setPreferences(\n\tpreferences: z.input<typeof DataSchema>['preferences'],\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: {\n\t\t\t...data?.preferences,\n\t\t\t...preferences,\n\t\t\tplayer: {\n\t\t\t\t...data?.preferences?.player,\n\t\t\t\t...preferences?.player,\n\t\t\t},\n\t\t\tpresence: {\n\t\t\t\t...data?.preferences?.presence,\n\t\t\t\t...preferences?.presence,\n\t\t\t},\n\t\t\texerciseWarning: {\n\t\t\t\t...data?.preferences?.exerciseWarning,\n\t\t\t\t...preferences?.exerciseWarning,\n\t\t\t},\n\t\t},\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.preferences\n}\n\nexport async function getMutedNotifications() {\n\tconst data = await readDb()\n\treturn data?.mutedNotifications ?? []\n}\n\nexport async function muteNotification(id: string) {\n\tconst data = await readDb()\n\tconst mutedNotifications = Array.from(\n\t\tnew Set([...(data?.mutedNotifications ?? []), id]),\n\t)\n\tconst updatedData = {\n\t\t...data,\n\t\tmutedNotifications,\n\t}\n\tawait saveJSON(updatedData)\n\treturn mutedNotifications\n}\n\nexport async function setFontSizePreference(fontSize: number | undefined) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: { ...data?.preferences, fontSize },\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.preferences.fontSize\n}\n\nexport async function getFontSizePreference() {\n\tconst data = await readDb()\n\treturn data?.preferences?.fontSize ?? null\n}\n\nexport async function readOnboardingData() {\n\tconst data = await readDb()\n\treturn data?.onboarding ?? null\n}\n\nexport async function markOnboardingVideoWatched(videoUrl: string) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tonboarding: {\n\t\t\t...data?.onboarding,\n\t\t\ttourVideosWatched: [\n\t\t\t\t...(data?.onboarding.tourVideosWatched ?? []),\n\t\t\t\tvideoUrl,\n\t\t\t].filter(Boolean),\n\t\t},\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.onboarding\n}\n\nexport async function unmarkOnboardingVideoWatched(videoUrl: string) {\n\tconst data = await readDb()\n\tconst watchedVideos = data?.onboarding?.tourVideosWatched ?? []\n\tconst updatedData = {\n\t\t...data,\n\t\tonboarding: {\n\t\t\t...data?.onboarding,\n\t\t\ttourVideosWatched: watchedVideos.filter((url) => url !== videoUrl),\n\t\t},\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.onboarding\n}\n\nexport async function areAllOnboardingVideosWatched(\n\tonboardingVideos: string[],\n) {\n\tconst data = await readDb()\n\tconst watchedVideos = data?.onboarding?.tourVideosWatched ?? []\n\treturn onboardingVideos.every((video) => watchedVideos.includes(video))\n}\n"]}
1
+ {"version":3,"file":"db.server.js","sourceRoot":"","sources":["../../src/db.server.ts"],"names":[],"mappings":"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","sourcesContent":["import './init-env.js'\n\nimport { randomUUID as cuid } from 'crypto'\nimport fsExtra from 'fs-extra'\nimport { redirect } from 'react-router'\nimport { z } from 'zod'\nimport { getWorkshopConfig } from './config.server.js'\nimport { saveJSON, loadJSON, migrateLegacyData } from './data-storage.server.js'\n\n// Attempt migration from legacy ~/.epicshop\nawait migrateLegacyData().catch(() => {})\n\nconst TokenSetSchema = z.object({\n\taccess_token: z.string(),\n\ttoken_type: z.string(),\n\tscope: z.string(),\n})\nexport const PlayerPreferencesSchema = z\n\t.object({\n\t\tminResolution: z.number().optional(),\n\t\tmaxResolution: z.number().optional(),\n\t\tvolumeRate: z.number().optional(),\n\t\tplaybackRate: z.number().optional(),\n\t\tautoplay: z.boolean().optional(),\n\t\tsubtitle: z\n\t\t\t.object({\n\t\t\t\tid: z.string().nullable().default(null),\n\t\t\t\tmode: z\n\t\t\t\t\t.literal('disabled')\n\t\t\t\t\t.or(z.literal('hidden'))\n\t\t\t\t\t.or(z.literal('showing'))\n\t\t\t\t\t.nullable()\n\t\t\t\t\t.default('disabled'),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.default({}),\n\t\tmuted: z.boolean().optional(),\n\t\ttheater: z.boolean().optional(),\n\t\tdefaultView: z.string().optional(),\n\t\tactiveSidebarTab: z.number().optional(),\n\t})\n\t.optional()\n\t.default({})\n\nconst PresencePreferencesSchema = z\n\t.object({\n\t\toptOut: z.boolean(),\n\t})\n\t.optional()\n\t.default({ optOut: false })\n\nconst AuthInfoSchema = z.object({\n\tid: z.string(),\n\ttokenSet: TokenSetSchema,\n\temail: z.string(),\n\tname: z.string().nullable().optional(),\n})\n\nconst MutedNotificationSchema = z.array(z.string()).default([])\n\nconst DataSchema = z.object({\n\tonboarding: z\n\t\t.object({\n\t\t\ttourVideosWatched: z.array(z.string()).default([]),\n\t\t})\n\t\t.passthrough()\n\t\t.optional()\n\t\t.default({ tourVideosWatched: [] }),\n\tpreferences: z\n\t\t.object({\n\t\t\tplayer: PlayerPreferencesSchema,\n\t\t\tpresence: PresencePreferencesSchema,\n\t\t\tplayground: z\n\t\t\t\t.object({\n\t\t\t\t\tpersist: z.boolean().default(false),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tfontSize: z.number().optional(),\n\t\t\texerciseWarning: z\n\t\t\t\t.object({\n\t\t\t\t\tdismissed: z.boolean().default(false),\n\t\t\t\t})\n\t\t\t\t.optional()\n\t\t\t\t.default({ dismissed: false }),\n\t\t})\n\t\t.optional()\n\t\t.default({}),\n\t// deprecated. Probably safe to remove in May 2026:\n\tauthInfo: AuthInfoSchema.optional(),\n\t// new:\n\tauthInfos: z.record(z.string(), AuthInfoSchema).optional(),\n\tclientId: z.string().optional(),\n\tmutedNotifications: MutedNotificationSchema.optional(),\n})\n\nexport async function getClientId() {\n\tconst data = await readDb()\n\tif (data?.clientId) return data.clientId\n\n\tconst clientId = cuid()\n\tawait saveJSON({ ...data, clientId })\n\treturn clientId\n}\n\nexport async function logout() {\n\tconst config = getWorkshopConfig()\n\tconst host = config.product.host\n\tif (host) {\n\t\tconst data = await readDb()\n\t\tconst newAuthInfos = { ...data?.authInfos }\n\t\tdelete newAuthInfos[host]\n\t\tawait saveJSON({\n\t\t\t...data,\n\t\t\tauthInfos: newAuthInfos,\n\t\t})\n\t}\n}\n\nexport async function deleteDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tconst { path: dbPath } = await loadJSON()\n\t\tif (dbPath && (await fsExtra.exists(dbPath))) {\n\t\t\tawait fsExtra.remove(dbPath)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(`Error deleting the database`, error)\n\t}\n}\n\nexport async function readDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\tconst maxRetries = 3\n\tconst baseDelay = 10\n\n\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\ttry {\n\t\t\tconst { data, path: dbPath } = await loadJSON()\n\t\t\tif (data && dbPath) {\n\t\t\t\tconst db = DataSchema.parse(data)\n\t\t\t\treturn db\n\t\t\t}\n\t\t\treturn null\n\t\t} catch (error) {\n\t\t\t// If this is a retry attempt, it might be a race condition\n\t\t\tif (attempt < maxRetries) {\n\t\t\t\tconst delay = baseDelay * Math.pow(2, attempt)\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Database read error on attempt ${attempt + 1}/${maxRetries + 1}, retrying in ${delay}ms...`,\n\t\t\t\t)\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay))\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Final attempt failed, handle as corrupted file\n\t\t\tconsole.error(\n\t\t\t\t`Error reading the database after ${attempt + 1} attempts, moving it to a .bkp file to avoid parsing errors in the future`,\n\t\t\t\terror,\n\t\t\t)\n\n\t\t\t// Log to Sentry if available\n\t\t\tif (process.env.SENTRY_DSN && process.env.EPICSHOP_IS_PUBLISHED) {\n\t\t\t\ttry {\n\t\t\t\t\tconst Sentry = await import('@sentry/react-router')\n\t\t\t\t\tSentry.captureException(error, {\n\t\t\t\t\t\ttags: {\n\t\t\t\t\t\t\terror_type: 'corrupted_database_file',\n\t\t\t\t\t\t\tretry_attempts: attempt.toString(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\textra: {\n\t\t\t\t\t\t\terrorMessage:\n\t\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\tretryAttempts: attempt,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t} catch (sentryError) {\n\t\t\t\t\tconsole.error('Failed to log to Sentry:', sentryError)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Try to move corrupted file to backup if we can determine the path\n\t\t\ttry {\n\t\t\t\tconst { path: dbPath } = await loadJSON()\n\t\t\t\tif (dbPath && (await fsExtra.exists(dbPath))) {\n\t\t\t\t\tvoid fsExtra.move(dbPath, `${dbPath}.bkp`).catch(() => {})\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\treturn null\n}\n\nexport async function getAuthInfo() {\n\tconst config = getWorkshopConfig()\n\tconst data = await readDb()\n\tif (config.product.host && typeof data?.authInfos === 'object') {\n\t\tif (config.product.host in data.authInfos) {\n\t\t\treturn data.authInfos[config.product.host]\n\t\t}\n\t}\n\n\t// special case for non-epicweb/epicreact workshops\n\tif (\n\t\t!config.product.host ||\n\t\tconfig.product.host === 'epicweb.dev' ||\n\t\tconfig.product.host === 'epicreact.dev'\n\t) {\n\t\t// upgrade from old authInfo to new authInfos\n\t\tif (data?.authInfo && config.product.host) {\n\t\t\tawait setAuthInfo(data.authInfo)\n\t\t}\n\t\treturn data?.authInfo ?? null\n\t}\n\n\treturn null\n}\n\nexport async function requireAuthInfo({\n\trequest,\n\tredirectTo,\n}: {\n\trequest: Request\n\tredirectTo?: string | null\n}) {\n\tconst authInfo = await getAuthInfo()\n\tif (!authInfo) {\n\t\tconst requestUrl = new URL(request.url)\n\t\tredirectTo =\n\t\t\tredirectTo === null\n\t\t\t\t? null\n\t\t\t\t: (redirectTo ?? `${requestUrl.pathname}${requestUrl.search}`)\n\t\tconst loginParams = redirectTo ? new URLSearchParams({ redirectTo }) : null\n\t\tconst loginRedirect = ['/login', loginParams?.toString()]\n\t\t\t.filter(Boolean)\n\t\t\t.join('?')\n\t\tthrow redirect(loginRedirect)\n\t}\n\treturn authInfo\n}\n\nexport async function setAuthInfo({\n\tid,\n\ttokenSet,\n\temail = 'unknown@example.com',\n\tname,\n}: {\n\tid: string\n\ttokenSet: Partial<z.infer<typeof TokenSetSchema>>\n\temail?: string | null\n\tname?: string | null\n}) {\n\tconst data = await readDb()\n\tconst authInfo = AuthInfoSchema.parse({ id, tokenSet, email, name })\n\tconst config = getWorkshopConfig()\n\tif (config.product.host) {\n\t\tawait saveJSON({\n\t\t\t...data,\n\t\t\tauthInfos: {\n\t\t\t\t...data?.authInfos,\n\t\t\t\t[config.product.host]: authInfo,\n\t\t\t},\n\t\t})\n\t} else {\n\t\tawait saveJSON({ ...data, authInfo })\n\t}\n\treturn authInfo\n}\n\nexport async function getPreferences() {\n\tconst data = await readDb()\n\treturn data?.preferences ?? null\n}\n\nexport async function setPreferences(\n\tpreferences: z.input<typeof DataSchema>['preferences'],\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: {\n\t\t\t...data?.preferences,\n\t\t\t...preferences,\n\t\t\tplayer: {\n\t\t\t\t...data?.preferences?.player,\n\t\t\t\t...preferences?.player,\n\t\t\t},\n\t\t\tpresence: {\n\t\t\t\t...data?.preferences?.presence,\n\t\t\t\t...preferences?.presence,\n\t\t\t},\n\t\t\texerciseWarning: {\n\t\t\t\t...data?.preferences?.exerciseWarning,\n\t\t\t\t...preferences?.exerciseWarning,\n\t\t\t},\n\t\t},\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.preferences\n}\n\nexport async function getMutedNotifications() {\n\tconst data = await readDb()\n\treturn data?.mutedNotifications ?? []\n}\n\nexport async function muteNotification(id: string) {\n\tconst data = await readDb()\n\tconst mutedNotifications = Array.from(\n\t\tnew Set([...(data?.mutedNotifications ?? []), id]),\n\t)\n\tconst updatedData = {\n\t\t...data,\n\t\tmutedNotifications,\n\t}\n\tawait saveJSON(updatedData)\n\treturn mutedNotifications\n}\n\nexport async function setFontSizePreference(fontSize: number | undefined) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: { ...data?.preferences, fontSize },\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.preferences.fontSize\n}\n\nexport async function getFontSizePreference() {\n\tconst data = await readDb()\n\treturn data?.preferences?.fontSize ?? null\n}\n\nexport async function readOnboardingData() {\n\tconst data = await readDb()\n\treturn data?.onboarding ?? null\n}\n\nexport async function markOnboardingVideoWatched(videoUrl: string) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tonboarding: {\n\t\t\t...data?.onboarding,\n\t\t\ttourVideosWatched: [\n\t\t\t\t...(data?.onboarding.tourVideosWatched ?? []),\n\t\t\t\tvideoUrl,\n\t\t\t].filter(Boolean),\n\t\t},\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.onboarding\n}\n\nexport async function unmarkOnboardingVideoWatched(videoUrl: string) {\n\tconst data = await readDb()\n\tconst watchedVideos = data?.onboarding?.tourVideosWatched ?? []\n\tconst updatedData = {\n\t\t...data,\n\t\tonboarding: {\n\t\t\t...data?.onboarding,\n\t\t\ttourVideosWatched: watchedVideos.filter((url) => url !== videoUrl),\n\t\t},\n\t}\n\tawait saveJSON(updatedData)\n\treturn updatedData.onboarding\n}\n\nexport async function areAllOnboardingVideosWatched(\n\tonboardingVideos: string[],\n) {\n\tconst data = await readDb()\n\tconst watchedVideos = data?.onboarding?.tourVideosWatched ?? []\n\treturn onboardingVideos.every((video) => watchedVideos.includes(video))\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"modified-time.server.d.ts","sourceRoot":"","sources":["../../src/modified-time.server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAQtB,iBAAe,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,EAAE,UAAkB,EAAE,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,OAAO,CAAC,MAAM,CAAC,CASjB;AA2CD,wBAAsB,wBAAwB,CAC7C,IAAI,EAAE,MAAM,EACZ,GAAG,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,oBAStB;AAgBD,iBAAe,wBAAwB,CACtC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,mBAK9C;AAED,OAAO,EAAE,wBAAwB,IAAI,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"modified-time.server.d.ts","sourceRoot":"","sources":["../../src/modified-time.server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAQtB,iBAAe,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,EAAE,UAAkB,EAAE,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,OAAO,CAAC,MAAM,CAAC,CASjB;AA2CD,wBAAsB,wBAAwB,CAC7C,IAAI,EAAE,MAAM,EACZ,GAAG,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,oBAStB;AAeD,iBAAe,wBAAwB,CACtC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,mBAK9C;AAED,OAAO,EAAE,wBAAwB,IAAI,kBAAkB,EAAE,CAAA"}
@@ -65,7 +65,6 @@ function getQueue() {
65
65
  return _queue;
66
66
  _queue = new PQueue({
67
67
  concurrency: 10,
68
- throwOnTimeout: true,
69
68
  timeout: 1000 * 60,
70
69
  });
71
70
  return _queue;
@@ -1 +1 @@
1
- {"version":3,"file":"modified-time.server.js","sourceRoot":"","sources":["../../src/modified-time.server.ts"],"names":[],"mappings":"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","sourcesContent":["import './init-env.js'\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { isGitIgnored } from 'globby'\nimport PQueue from 'p-queue'\nimport { cachified, dirModifiedTimeCache } from './cache.server.js'\n\nasync function getDirModifiedTime(\n\tdir: string,\n\t{ forceFresh = false }: { forceFresh?: boolean } = {},\n): Promise<number> {\n\tconst result = await cachified({\n\t\tkey: dir,\n\t\tcache: dirModifiedTimeCache,\n\t\tttl: 200,\n\t\tforceFresh,\n\t\tgetFreshValue: () => getDirModifiedTimeImpl(dir),\n\t})\n\treturn result\n}\n\nasync function getDirModifiedTimeImpl(dir: string): Promise<number> {\n\tconst isIgnored = await isGitIgnored({ cwd: dir }).catch(() => () => false)\n\tconst files = await fs.promises\n\t\t.readdir(dir, { withFileTypes: true })\n\t\t.catch(() => [])\n\n\tconst modifiedTimes: Array<number> = []\n\n\tfor (const file of files) {\n\t\t// Skip ignored files\n\t\tif (isIgnored(path.join(dir, file.name))) continue\n\n\t\tconst filePath = path.join(dir, file.name)\n\n\t\tif (file.isDirectory()) {\n\t\t\tmodifiedTimes.push(await getDirModifiedTime(filePath))\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst { mtimeMs } = await fs.promises.stat(filePath)\n\t\t\t\tmodifiedTimes.push(mtimeMs)\n\t\t\t} catch {\n\t\t\t\t// ignore errors (e.g., file access permissions, file has been moved or deleted)\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\tconst { mtimeMs } = await fs.promises.stat(dir)\n\t\tmodifiedTimes.push(mtimeMs)\n\t} catch {\n\t\t// ignore errors (e.g., file access permissions, file has been moved or deleted)\n\t}\n\n\treturn Math.max(-1, ...modifiedTimes)\n}\n\n// this will return true as soon as one of the directories has been found to\n// have been modified more recently than the given time\n// TODO: this could be improved by not waiting for entire directories to be\n// scanned and instead stopping the scan as soon as we find a file that was\n// modified more recently than the given time\nexport async function modifiedMoreRecentlyThan(\n\ttime: number,\n\t...dirs: Array<string>\n) {\n\tconst modifiedTimePromises = dirs.map((dir) => getDirModifiedTime(dir))\n\tconst allFinishedPromise = Promise.all(modifiedTimePromises)\n\tconst firstMoreRecentPromise = modifiedTimePromises.map((p) =>\n\t\tp.then((t) => (t > time ? true : allFinishedPromise.then(() => false))),\n\t)\n\tconst firstMoreRecent = await Promise.race(firstMoreRecentPromise)\n\treturn firstMoreRecent\n}\n\nlet _queue: PQueue | null = null\nfunction getQueue() {\n\tif (_queue) return _queue\n\n\t_queue = new PQueue({\n\t\tconcurrency: 10,\n\t\tthrowOnTimeout: true,\n\t\ttimeout: 1000 * 60,\n\t})\n\treturn _queue\n}\n\n// We have to use a queue because we can't run more than one of these at a time\n// or we'll hit an out of memory error because esbuild uses a lot of memory...\nasync function queuedGetDirModifiedTime(\n\t...args: Parameters<typeof getDirModifiedTime>\n) {\n\tconst queue = getQueue()\n\tconst result = await queue.add(() => getDirModifiedTime(...args))\n\treturn result || -1\n}\n\nexport { queuedGetDirModifiedTime as getDirModifiedTime }\n"]}
1
+ {"version":3,"file":"modified-time.server.js","sourceRoot":"","sources":["../../src/modified-time.server.ts"],"names":[],"mappings":"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","sourcesContent":["import './init-env.js'\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { isGitIgnored } from 'globby'\nimport PQueue from 'p-queue'\nimport { cachified, dirModifiedTimeCache } from './cache.server.js'\n\nasync function getDirModifiedTime(\n\tdir: string,\n\t{ forceFresh = false }: { forceFresh?: boolean } = {},\n): Promise<number> {\n\tconst result = await cachified({\n\t\tkey: dir,\n\t\tcache: dirModifiedTimeCache,\n\t\tttl: 200,\n\t\tforceFresh,\n\t\tgetFreshValue: () => getDirModifiedTimeImpl(dir),\n\t})\n\treturn result\n}\n\nasync function getDirModifiedTimeImpl(dir: string): Promise<number> {\n\tconst isIgnored = await isGitIgnored({ cwd: dir }).catch(() => () => false)\n\tconst files = await fs.promises\n\t\t.readdir(dir, { withFileTypes: true })\n\t\t.catch(() => [])\n\n\tconst modifiedTimes: Array<number> = []\n\n\tfor (const file of files) {\n\t\t// Skip ignored files\n\t\tif (isIgnored(path.join(dir, file.name))) continue\n\n\t\tconst filePath = path.join(dir, file.name)\n\n\t\tif (file.isDirectory()) {\n\t\t\tmodifiedTimes.push(await getDirModifiedTime(filePath))\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst { mtimeMs } = await fs.promises.stat(filePath)\n\t\t\t\tmodifiedTimes.push(mtimeMs)\n\t\t\t} catch {\n\t\t\t\t// ignore errors (e.g., file access permissions, file has been moved or deleted)\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\tconst { mtimeMs } = await fs.promises.stat(dir)\n\t\tmodifiedTimes.push(mtimeMs)\n\t} catch {\n\t\t// ignore errors (e.g., file access permissions, file has been moved or deleted)\n\t}\n\n\treturn Math.max(-1, ...modifiedTimes)\n}\n\n// this will return true as soon as one of the directories has been found to\n// have been modified more recently than the given time\n// TODO: this could be improved by not waiting for entire directories to be\n// scanned and instead stopping the scan as soon as we find a file that was\n// modified more recently than the given time\nexport async function modifiedMoreRecentlyThan(\n\ttime: number,\n\t...dirs: Array<string>\n) {\n\tconst modifiedTimePromises = dirs.map((dir) => getDirModifiedTime(dir))\n\tconst allFinishedPromise = Promise.all(modifiedTimePromises)\n\tconst firstMoreRecentPromise = modifiedTimePromises.map((p) =>\n\t\tp.then((t) => (t > time ? true : allFinishedPromise.then(() => false))),\n\t)\n\tconst firstMoreRecent = await Promise.race(firstMoreRecentPromise)\n\treturn firstMoreRecent\n}\n\nlet _queue: PQueue | null = null\nfunction getQueue() {\n\tif (_queue) return _queue\n\n\t_queue = new PQueue({\n\t\tconcurrency: 10,\n\t\ttimeout: 1000 * 60,\n\t})\n\treturn _queue\n}\n\n// We have to use a queue because we can't run more than one of these at a time\n// or we'll hit an out of memory error because esbuild uses a lot of memory...\nasync function queuedGetDirModifiedTime(\n\t...args: Parameters<typeof getDirModifiedTime>\n) {\n\tconst queue = getQueue()\n\tconst result = await queue.add(() => getDirModifiedTime(...args))\n\treturn result || -1\n}\n\nexport { queuedGetDirModifiedTime as getDirModifiedTime }\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.server.d.ts","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAIxD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAG7C,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAS3C,KAAK,eAAe,GAAG,GAAG,CACzB,MAAM,EACN;IACC,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;CACZ,CACD,CAAA;AAED,KAAK,mBAAmB,GAAG,GAAG,CAC7B,MAAM,EACN;IACC,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,YAAY,CAAA;CACrB,CACD,CAAA;AAED,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACvB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,KAAK,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AACrD,OAAO,CAAC,MAAM,CAAC;IACd,IAAI,uCAAuC,EAAE,UAAU,CACrD,OAAO,cAAc,CACrB,EACD,wCAAwC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,EAC3E,2CAA2C,EAAE,UAAU,CACtD,OAAO,cAAc,CACrB,CAAA;CACF;AAoDD,QAAA,MAAM,MAAM,mIAWF,CAAA;AA4BV,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;GAgEvC;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG;;;GAkDzC;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;UAwBvC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,oBASvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAUlD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,gCAExD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAE1D;AAED,wBAAgB,YAAY;;;;EAE3B;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAStE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAqEhE;AAED,wBAAgB,oBAAoB,SASnC;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,iBAwB7C;AAID,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAInD;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAWnE"}
1
+ {"version":3,"file":"process-manager.server.d.ts","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAIxD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAG7C,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAS3C,KAAK,eAAe,GAAG,GAAG,CACzB,MAAM,EACN;IACC,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;CACZ,CACD,CAAA;AAED,KAAK,mBAAmB,GAAG,GAAG,CAC7B,MAAM,EACN;IACC,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,YAAY,CAAA;CACrB,CACD,CAAA;AAED,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACvB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,KAAK,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AACrD,OAAO,CAAC,MAAM,CAAC;IACd,IAAI,uCAAuC,EAAE,UAAU,CACrD,OAAO,cAAc,CACrB,EACD,wCAAwC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,EAC3E,2CAA2C,EAAE,UAAU,CACtD,OAAO,cAAc,CACrB,CAAA;CACF;AAoDD,QAAA,MAAM,MAAM,mIAWF,CAAA;AA4BV,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;GAgEvC;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG;;;GAkDzC;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;UAwBvC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,oBAWvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAUlD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,gCAExD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAE1D;AAED,wBAAgB,YAAY;;;;EAE3B;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAStE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAqEhE;AAED,wBAAgB,oBAAoB,SASnC;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,iBAwB7C;AAID,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAInD;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAWnE"}
@@ -228,6 +228,8 @@ export async function isAppRunning(app) {
228
228
  const devProcess = devProcesses.get(app.name);
229
229
  if (!devProcess?.process.pid)
230
230
  return false;
231
+ // @ts-ignore - find-process is not typed correctly
232
+ // https://github.com/yibn2008/find-process/issues/85
231
233
  const found = await findProcess('pid', devProcess.process.pid);
232
234
  return found.length > 0;
233
235
  }
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.server.js","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAAE,KAAK,EAAqB,MAAM,eAAe,CAAA;AACxD,OAAO,GAAG,MAAM,UAAU,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,WAAW,MAAM,cAAc,CAAA;AACtC,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,UAAU,GACf,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,MAAM;IACxC,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,CAAA;AA0CtC,MAAM,YAAY,GAAG,QAAQ,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAA;AAClE,MAAM,aAAa,GAAG,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAA;AACrE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,CAAA;AAE9E,SAAS,kBAAkB;IAC1B,MAAM,KAAK,GAAoB,IAAI,GAAG,EAAE,CAAA;IAExC,MAAM,CAAC,uCAAuC,EAAE,SAAS,EAAE,CAAA;IAE3D,MAAM,CAAC,uCAAuC,GAAG,cAAc,CAAC,KAAK,IAAI,EAAE;QAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACpB,CAAC;IACF,CAAC,CAAC,CAAA;IACF,OAAO,KAAK,CAAA;AACb,CAAC;AAED,SAAS,mBAAmB;IAC3B,MAAM,KAAK,GAAqB,IAAI,GAAG,EAAE,CAAA;IAEzC,MAAM,CAAC,wCAAwC,EAAE,SAAS,EAAE,CAAA;IAE5D,MAAM,CAAC,wCAAwC,GAAG,cAAc,CAAC,KAAK,IAAI,EAAE;QAC3E,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;YACpB,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAA;IACF,OAAO,KAAK,CAAA;AACb,CAAC;AAED,SAAS,sBAAsB;IAC9B,MAAM,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAA;IAE5C,MAAM,CAAC,2CAA2C,EAAE,SAAS,EAAE,CAAA;IAE/D,MAAM,CAAC,2CAA2C,GAAG,cAAc,CAClE,KAAK,IAAI,EAAE;QACV,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAA;YACpC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACpB,CAAC;IACF,CAAC,CACD,CAAA;IACD,OAAO,KAAK,CAAA;AACb,CAAC;AAED,MAAM,MAAM,GAAG;IACd,MAAM;IACN,OAAO;IACP,QAAQ;IACR,KAAK;IACL,SAAS;IACT,WAAW;IACX,aAAa;IACb,cAAc;IACd,YAAY;IACZ,eAAe;CACN,CAAA;AAEV,SAAS,qBAAqB;IAC7B,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAA;IAErD,uCAAuC;IACvC,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1C,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;IAED,2CAA2C;IAC3C,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;IAED,wBAAwB;IACxB,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IAExE,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,0EAA0E;QAC1E,MAAM,cAAc,GAAG,YAAY,CAAC,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAA;QAChE,OAAO,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAA;IACxD,CAAC;IAED,gCAAgC;IAChC,OAAO,eAAe,CAAC,CAAC,CAAC,IAAI,MAAM,CAAA;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAQ;IACvC,IAAI,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACnE,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAA;IACpB,sDAAsD;IACtD,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAW,CAAA;IAC7D,CAAC;IAED,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAW,CAAA;IACxD,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,GAAG,CAAA;IAC9B,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAW,CAAA;IAC3E,CAAC;IACD,MAAM,KAAK,GAAG,qBAAqB,EAAE,CAAA;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE;QAC3D,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,GAAG,EAAE;YACJ,GAAG,OAAO,CAAC,GAAG;YACd,mCAAmC;YACnC,QAAQ,EAAE,aAAa;YACvB,oCAAoC;YACpC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC;YACxB,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC;YACnC,+BAA+B;YAC/B,wBAAwB,EAAE,EAAE;SAC5B;KACD,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAC1B,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,IAAI,UAAU,GAAG,CACzD,CAAA;IACD,SAAS,gBAAgB,CAAC,IAAY;QACrC,OAAO,CAAC,GAAG,CACV,IAAI;aACF,QAAQ,CAAC,OAAO,CAAC;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAA;IACF,CAAC;IACD,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC9C,SAAS,gBAAgB,CAAC,IAAY;QACrC,OAAO,CAAC,KAAK,CACZ,IAAI;aACF,QAAQ,CAAC,OAAO,CAAC;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAA;IACF,CAAC;IACD,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC9C,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAC9B,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QAC/C,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,YAAY,IAAI,GAAG,CAAC,CAAA;QACzC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAW,CAAA;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAQ;IACzC,IAAI,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IACpE,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAA;IAEpB,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAW,CAAA;IACtD,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE;QAC7D,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,GAAG,EAAE;YACJ,GAAG,OAAO,CAAC,GAAG;YACd,mCAAmC;YACnC,QAAQ,EAAE,aAAa;YACvB,oCAAoC;YACpC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;YACxE,eAAe,EACd,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;YACnE,+BAA+B;YAC/B,wBAAwB,EAAE,EAAE;SAC5B;KACD,CAAC,CAAA;IACF,MAAM,MAAM,GAAsB,EAAE,CAAA;IACpC,MAAM,KAAK,GAAqB,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAA;IAChE,SAAS,gBAAgB,CAAC,IAAY;QACrC,MAAM,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC/B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAA;IACH,CAAC;IACD,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC/C,SAAS,gBAAgB,CAAC,IAAY;QACrC,MAAM,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC/B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAA;IACH,CAAC;IACD,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC/C,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAC/B,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QAChD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QAChD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAA;QACpB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;IACtB,CAAC,CAAC,CAAA;IACF,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC7B,OAAO,WAAW,CAAA;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAQ;IACvC,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAE5B,MAAM,aAAa,GAAG,GAAG,CAAA;QACzB,MAAM,OAAO,GAAG,MAAM,CAAA;QACtB,IAAI,SAAkB,CAAA;QACtB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,OAAO,EAAE,CAAC;YACzC,IAAI,CAAC;gBACJ,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;gBAC9C,MAAM,KAAK,CAAC,GAAG,EAAE;oBAChB,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;iBAC1B,CAAC,CAAA;gBACF,OAAO,EAAE,MAAM,EAAE,SAAS,EAAW,CAAA;YACtC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,SAAS,GAAG,KAAK,CAAA;gBACjB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAA;YACnE,CAAC;QACF,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,EAAW,CAAA;IACvE,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAqB;IACpD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAA;QACjC,MAAM,CAAC,KAAK,EAAE,CAAA;QACd,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAExC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE;YAChC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBACjB,OAAO,CAAC,IAAI,CAAC,CAAA;YACd,CAAC,CAAC,CAAA;QACH,CAAC,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAqB;IACvD,IAAI,CAAC;QACJ,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC7C,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG;YAAE,OAAO,KAAK,CAAA;QAC1C,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC9D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAqB;IAClD,IAAI,CAAC;QACJ,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC/C,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAA;QAC9B,IAAI,WAAW,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;QAC9C,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC3B,OAAO,IAAI,CAAA;IACZ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAqB;IACxD,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACnC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAqB;IAC1D,OAAO,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,YAAY;IAC3B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,SAAiC;IACtE,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAA;QACnE,OAAM;IACP,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACnC,CAAC;AACF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAe;IAChE,IAAI,UAAU;QACb,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAEjE,0DAA0D;IAC1D,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,qBAAqB,CAAC,CAAA;QACzD,OAAM;IACP,CAAC;IAED,MAAM,KAAK,GAAG,qBAAqB,EAAE,CAAA;IAErC,oEAAoE;IACpE,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,oBAAoB,CAAA;IAClD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE;QACzC,KAAK,EAAE,IAAI;QACX,GAAG,EAAE,YAAY;QACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,GAAG,EAAE;YACJ,GAAG,OAAO,CAAC,GAAG;YACd,QAAQ,EAAE,aAAa;SACvB;KACD,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAA;IAExC,SAAS,gBAAgB,CAAC,IAAY;QACrC,OAAO,CAAC,GAAG,CACV,IAAI;aACF,QAAQ,CAAC,OAAO,CAAC;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAA;IACF,CAAC;IACD,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAEnD,SAAS,gBAAgB,CAAC,IAAY;QACrC,OAAO,CAAC,KAAK,CACZ,IAAI;aACF,QAAQ,CAAC,OAAO,CAAC;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAA;IACF,CAAC;IACD,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAEnD,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAA;IAE9D,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAmB,EAAE,MAAqB,EAAE,EAAE;QACxE,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QACpD,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QACpD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,sBAAsB,CAAC,CAAA;QAC7C,CAAC;aAAM,CAAC;YACP,OAAO,CAAC,GAAG,CACV,GAAG,MAAM,qBAAqB,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3E,CAAA;QACF,CAAC;QACD,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACpC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,qBAAqB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC5D,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,UAAU,CAAC,CAAA;AACjC,CAAC;AAED,MAAM,UAAU,oBAAoB;IACnC,IAAI,UAAU;QACb,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IAElE,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAA;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;IACpB,CAAC;IACD,gBAAgB,CAAC,KAAK,EAAE,CAAA;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC7C,IAAI,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC1E,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAClC,IAAI,IAAI,EAAE,CAAC;QACV,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAChC,CAAA;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAClC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAA;YACvC,IAAI,CAAC;gBACJ,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;YACxE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,OAAO,CAAC,KAAK,CAAC,8BAA8B,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,CAAA;YACtE,CAAC;QACF,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACpB,CAAC;QACD,MAAM,OAAO,CAAC,IAAI,CAAC;YAClB,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAClD,aAAa;SACb,CAAC,CAAA;QACF,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAC,qBAAqB;QAC/C,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;AACF,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;AAE7E,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAqB;IACnD,IAAI,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACrE,MAAM,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,MAAM,wBAAwB,CAAC,IAAI,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,IAAqB;IACnE,8CAA8C;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAA;IACnC,IAAI,aAAa,GAAG,KAAK,CAAA;IACzB,GAAG,CAAC;QACH,aAAa,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;QAC3C,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IACjB,CAAC,QAAQ,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAC;IAChD,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACpE,CAAC;AACF,CAAC","sourcesContent":["import './init-env.js'\n\nimport { spawn, type ChildProcess } from 'child_process'\nimport net from 'node:net'\nimport { remember } from '@epic-web/remember'\nimport chalk from 'chalk'\nimport closeWithGrace from 'close-with-grace'\nimport findProcess from 'find-process'\nimport fkill from 'fkill'\nimport { type App } from './apps.server.js'\nimport { getWorkshopUrl } from './config.server.js'\nimport { getEnv } from './env.server.js'\nimport { getErrorMessage } from './utils.js'\n\nconst isDeployed =\n\tprocess.env.EPICSHOP_DEPLOYED === 'true' ||\n\tprocess.env.EPICSHOP_DEPLOYED === '1'\n\ntype DevProcessesMap = Map<\n\tstring,\n\t{\n\t\tcolor: (typeof colors)[number]\n\t\tprocess: ChildProcess\n\t\tport: number\n\t}\n>\n\ntype SidecarProcessesMap = Map<\n\tstring,\n\t{\n\t\tcolor: (typeof colors)[number]\n\t\tprocess: ChildProcess\n\t}\n>\n\ntype OutputLine = {\n\ttype: 'stdout' | 'stderr'\n\tcontent: string\n\ttimestamp: number\n}\n\ntype TestProcessEntry = {\n\tprocess: ChildProcess | null\n\toutput: Array<OutputLine>\n\texitCode?: number | null\n}\n\ntype TestProcessesMap = Map<string, TestProcessEntry>\ndeclare global {\n\tvar __process_dev_close_with_grace_return__: ReturnType<\n\t\t\ttypeof closeWithGrace\n\t\t>,\n\t\t__process_test_close_with_grace_return__: ReturnType<typeof closeWithGrace>,\n\t\t__process_sidecar_close_with_grace_return__: ReturnType<\n\t\t\ttypeof closeWithGrace\n\t\t>\n}\n\nconst devProcesses = remember('dev_processes', getDevProcessesMap)\nconst testProcesses = remember('test_processes', getTestProcessesMap)\nconst sidecarProcesses = remember('sidecar_processes', getSidecarProcessesMap)\n\nfunction getDevProcessesMap() {\n\tconst procs: DevProcessesMap = new Map()\n\n\tglobal.__process_dev_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_dev_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [name, proc] of procs.entries()) {\n\t\t\tconsole.log('closing', name)\n\t\t\tproc.process.kill()\n\t\t}\n\t})\n\treturn procs\n}\n\nfunction getTestProcessesMap() {\n\tconst procs: TestProcessesMap = new Map()\n\n\tglobal.__process_test_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_test_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [id, proc] of procs.entries()) {\n\t\t\tif (proc.process) {\n\t\t\t\tconsole.log('closing', id)\n\t\t\t\tproc.process.kill()\n\t\t\t}\n\t\t}\n\t})\n\treturn procs\n}\n\nfunction getSidecarProcessesMap() {\n\tconst procs: SidecarProcessesMap = new Map()\n\n\tglobal.__process_sidecar_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_sidecar_close_with_grace_return__ = closeWithGrace(\n\t\tasync () => {\n\t\t\tfor (const [name, proc] of procs.entries()) {\n\t\t\t\tconsole.log('closing sidecar', name)\n\t\t\t\tproc.process.kill()\n\t\t\t}\n\t\t},\n\t)\n\treturn procs\n}\n\nconst colors = [\n\t'blue',\n\t'green',\n\t'yellow',\n\t'red',\n\t'magenta',\n\t'redBright',\n\t'greenBright',\n\t'yellowBright',\n\t'blueBright',\n\t'magentaBright',\n] as const\n\nfunction getNextAvailableColor(): (typeof colors)[number] {\n\tconst usedColors = new Set<(typeof colors)[number]>()\n\n\t// Collect colors used by dev processes\n\tfor (const proc of devProcesses.values()) {\n\t\tusedColors.add(proc.color)\n\t}\n\n\t// Collect colors used by sidecar processes\n\tfor (const proc of sidecarProcesses.values()) {\n\t\tusedColors.add(proc.color)\n\t}\n\n\t// Find available colors\n\tconst availableColors = colors.filter((color) => !usedColors.has(color))\n\n\tif (availableColors.length === 0) {\n\t\t// If all colors are used, cycle through them based on total process count\n\t\tconst totalProcesses = devProcesses.size + sidecarProcesses.size\n\t\treturn colors[totalProcesses % colors.length] ?? 'blue'\n\t}\n\n\t// Use the first available color\n\treturn availableColors[0] ?? 'blue'\n}\n\nexport async function runAppDev(app: App) {\n\tif (isDeployed) throw new Error('cannot run apps in deployed mode')\n\tconst key = app.name\n\t// if the app is already running, don't start it again\n\tif (devProcesses.has(key)) {\n\t\treturn { status: 'process-running', running: true } as const\n\t}\n\n\tif (app.dev.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-server' } as const\n\t}\n\n\tconst { portNumber } = app.dev\n\tif (!(await isPortAvailable(portNumber))) {\n\t\treturn { status: 'port-unavailable', running: false, portNumber } as const\n\t}\n\tconst color = getNextAvailableColor()\n\tconst appProcess = spawn('npm', ['run', 'dev', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: String(portNumber),\n\t\t\tAPP_SERVER_PORT: String(portNumber),\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst prefix = chalk[color](\n\t\t`[${app.name.replace(/^exercises\\./, '')}:${portNumber}]`,\n\t)\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stderr.on('data', handleStdErrData)\n\tdevProcesses.set(key, { color, process: appProcess, port: portNumber })\n\tappProcess.on('exit', (code) => {\n\t\tappProcess.stdout.off('data', handleStdOutData)\n\t\tappProcess.stderr.off('data', handleStdErrData)\n\t\tconsole.log(`${prefix} exited (${code})`)\n\t\tdevProcesses.delete(key)\n\t})\n\n\treturn { status: 'process-started', running: true } as const\n}\n\nexport async function runAppTests(app: App) {\n\tif (isDeployed) throw new Error('cannot run tests in deployed mode')\n\tconst key = app.name\n\n\tif (app.test.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-test' } as const\n\t}\n\n\tconst testProcess = spawn('npm', ['run', 'test', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: app.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\tAPP_SERVER_PORT:\n\t\t\t\tapp.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst output: Array<OutputLine> = []\n\tconst entry: TestProcessEntry = { process: testProcess, output }\n\tfunction handleStdOutData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stdout',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stderr',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stderr.on('data', handleStdErrData)\n\ttestProcess.on('exit', (code) => {\n\t\ttestProcess.stdout.off('data', handleStdOutData)\n\t\ttestProcess.stderr.off('data', handleStdErrData)\n\t\tentry.process = null\n\t\tentry.exitCode = code\n\t})\n\ttestProcesses.set(key, entry)\n\treturn testProcess\n}\n\nexport async function waitOnApp(app: App) {\n\tif (app.dev.type === 'script') {\n\t\tconst startTime = Date.now()\n\n\t\tconst retryInterval = 100\n\t\tconst timeout = 20_000\n\t\tlet lastError: unknown\n\t\twhile (Date.now() - startTime < timeout) {\n\t\t\ttry {\n\t\t\t\tconst url = getWorkshopUrl(app.dev.portNumber)\n\t\t\t\tawait fetch(url, {\n\t\t\t\t\tmethod: 'HEAD',\n\t\t\t\t\theaders: { Accept: '*/*' },\n\t\t\t\t})\n\t\t\t\treturn { status: 'success' } as const\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, retryInterval))\n\t\t\t}\n\t\t}\n\n\t\treturn { status: 'error', error: getErrorMessage(lastError) } as const\n\t}\n\treturn null\n}\n\nexport function isPortAvailable(port: number | string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\t\tserver.unref()\n\t\tserver.on('error', () => resolve(false))\n\n\t\tserver.listen(Number(port), () => {\n\t\t\tserver.close(() => {\n\t\t\t\tresolve(true)\n\t\t\t})\n\t\t})\n\t})\n}\n\nexport async function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess?.process.pid) return false\n\t\tconst found = await findProcess('pid', devProcess.process.pid)\n\t\treturn found.length > 0\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function isTestRunning(app: { name: string }) {\n\ttry {\n\t\tconst testProcess = testProcesses.get(app.name)\n\t\tif (!testProcess) return false\n\t\tif (testProcess.process === null) return false\n\t\ttestProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function getTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.get(app.name)\n}\n\nexport function clearTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.delete(app.name)\n}\n\nexport function getProcesses() {\n\treturn { devProcesses, testProcesses, sidecarProcesses }\n}\n\nexport function startSidecarProcesses(processes: Record<string, string>) {\n\tif (isDeployed) {\n\t\tconsole.log('Sidecar processes are not supported in deployed mode')\n\t\treturn\n\t}\n\n\tfor (const [name, command] of Object.entries(processes)) {\n\t\tstartSidecarProcess(name, command)\n\t}\n}\n\nexport function startSidecarProcess(name: string, command: string) {\n\tif (isDeployed)\n\t\tthrow new Error('cannot run sidecar processes in deployed mode')\n\n\t// if the process is already running, don't start it again\n\tif (sidecarProcesses.has(name)) {\n\t\tconsole.log(`Sidecar process ${name} is already running`)\n\t\treturn\n\t}\n\n\tconst color = getNextAvailableColor()\n\n\t// Spawn the command using shell to handle complex commands properly\n\tconst workshopRoot = getEnv().EPICSHOP_CONTEXT_CWD\n\tconst sidecarProcess = spawn(command, [], {\n\t\tshell: true,\n\t\tcwd: workshopRoot,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\tNODE_ENV: 'development',\n\t\t},\n\t})\n\n\tconst prefix = chalk[color](`[${name}]`)\n\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tsidecarProcess.stdout?.on('data', handleStdOutData)\n\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tsidecarProcess.stderr?.on('data', handleStdErrData)\n\n\tsidecarProcesses.set(name, { color, process: sidecarProcess })\n\n\tsidecarProcess.on('exit', (code: number | null, signal: string | null) => {\n\t\tsidecarProcess.stdout?.off('data', handleStdOutData)\n\t\tsidecarProcess.stderr?.off('data', handleStdErrData)\n\t\tif (code === 0) {\n\t\t\tconsole.log(`${prefix} exited successfully`)\n\t\t} else {\n\t\t\tconsole.log(\n\t\t\t\t`${prefix} exited with code ${code}${signal ? ` (signal: ${signal})` : ''}`,\n\t\t\t)\n\t\t}\n\t\tsidecarProcesses.delete(name)\n\t})\n\n\tsidecarProcess.on('error', (error) => {\n\t\tconsole.error(`${prefix} failed to start: ${error.message}`)\n\t\tsidecarProcesses.delete(name)\n\t})\n\n\tconsole.log(`${prefix} started`)\n}\n\nexport function stopSidecarProcesses() {\n\tif (isDeployed)\n\t\tthrow new Error('cannot stop sidecar processes in deployed mode')\n\n\tfor (const [name, proc] of sidecarProcesses.entries()) {\n\t\tconsole.log(`Stopping sidecar process: ${name}`)\n\t\tproc.process.kill()\n\t}\n\tsidecarProcesses.clear()\n}\n\nexport async function closeProcess(key: string) {\n\tif (isDeployed) throw new Error('cannot close processes in deployed mode')\n\tconst proc = devProcesses.get(key)\n\tif (proc) {\n\t\tconst exitedPromise = new Promise((resolve) =>\n\t\t\tproc.process.on('exit', resolve),\n\t\t)\n\t\tif (process.platform === 'win32') {\n\t\t\tconst { execa } = await import('execa')\n\t\t\ttry {\n\t\t\t\tawait execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/t'])\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`Failed to taskkill process ${proc.process.pid}:`, err)\n\t\t\t}\n\t\t} else {\n\t\t\tproc.process.kill()\n\t\t}\n\t\tawait Promise.race([\n\t\t\tnew Promise((resolve) => setTimeout(resolve, 500)),\n\t\t\texitedPromise,\n\t\t])\n\t\tawait stopPort(proc.port) // just in case 🤷‍♂️\n\t\tdevProcesses.delete(key)\n\t}\n}\n\nconst sleep = (t: number) => new Promise((resolve) => setTimeout(resolve, t))\n\nexport async function stopPort(port: string | number) {\n\tif (isDeployed) throw new Error('cannot stop ports in deployed mode')\n\tawait fkill(`:${port}`, { force: true, silent: true })\n\tawait waitForPortToBeAvailable(port)\n}\n\nexport async function waitForPortToBeAvailable(port: string | number) {\n\t// wait for the port to become available again\n\tconst timeout = Date.now() + 10_000\n\tlet portAvailable = false\n\tdo {\n\t\tportAvailable = await isPortAvailable(port)\n\t\tawait sleep(100)\n\t} while (!portAvailable && Date.now() < timeout)\n\tif (!portAvailable) {\n\t\tconsole.error('Timed out waiting for the port to become available')\n\t}\n}\n"]}
1
+ {"version":3,"file":"process-manager.server.js","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"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","sourcesContent":["import './init-env.js'\n\nimport { spawn, type ChildProcess } from 'child_process'\nimport net from 'node:net'\nimport { remember } from '@epic-web/remember'\nimport chalk from 'chalk'\nimport closeWithGrace from 'close-with-grace'\nimport findProcess from 'find-process'\nimport fkill from 'fkill'\nimport { type App } from './apps.server.js'\nimport { getWorkshopUrl } from './config.server.js'\nimport { getEnv } from './env.server.js'\nimport { getErrorMessage } from './utils.js'\n\nconst isDeployed =\n\tprocess.env.EPICSHOP_DEPLOYED === 'true' ||\n\tprocess.env.EPICSHOP_DEPLOYED === '1'\n\ntype DevProcessesMap = Map<\n\tstring,\n\t{\n\t\tcolor: (typeof colors)[number]\n\t\tprocess: ChildProcess\n\t\tport: number\n\t}\n>\n\ntype SidecarProcessesMap = Map<\n\tstring,\n\t{\n\t\tcolor: (typeof colors)[number]\n\t\tprocess: ChildProcess\n\t}\n>\n\ntype OutputLine = {\n\ttype: 'stdout' | 'stderr'\n\tcontent: string\n\ttimestamp: number\n}\n\ntype TestProcessEntry = {\n\tprocess: ChildProcess | null\n\toutput: Array<OutputLine>\n\texitCode?: number | null\n}\n\ntype TestProcessesMap = Map<string, TestProcessEntry>\ndeclare global {\n\tvar __process_dev_close_with_grace_return__: ReturnType<\n\t\t\ttypeof closeWithGrace\n\t\t>,\n\t\t__process_test_close_with_grace_return__: ReturnType<typeof closeWithGrace>,\n\t\t__process_sidecar_close_with_grace_return__: ReturnType<\n\t\t\ttypeof closeWithGrace\n\t\t>\n}\n\nconst devProcesses = remember('dev_processes', getDevProcessesMap)\nconst testProcesses = remember('test_processes', getTestProcessesMap)\nconst sidecarProcesses = remember('sidecar_processes', getSidecarProcessesMap)\n\nfunction getDevProcessesMap() {\n\tconst procs: DevProcessesMap = new Map()\n\n\tglobal.__process_dev_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_dev_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [name, proc] of procs.entries()) {\n\t\t\tconsole.log('closing', name)\n\t\t\tproc.process.kill()\n\t\t}\n\t})\n\treturn procs\n}\n\nfunction getTestProcessesMap() {\n\tconst procs: TestProcessesMap = new Map()\n\n\tglobal.__process_test_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_test_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [id, proc] of procs.entries()) {\n\t\t\tif (proc.process) {\n\t\t\t\tconsole.log('closing', id)\n\t\t\t\tproc.process.kill()\n\t\t\t}\n\t\t}\n\t})\n\treturn procs\n}\n\nfunction getSidecarProcessesMap() {\n\tconst procs: SidecarProcessesMap = new Map()\n\n\tglobal.__process_sidecar_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_sidecar_close_with_grace_return__ = closeWithGrace(\n\t\tasync () => {\n\t\t\tfor (const [name, proc] of procs.entries()) {\n\t\t\t\tconsole.log('closing sidecar', name)\n\t\t\t\tproc.process.kill()\n\t\t\t}\n\t\t},\n\t)\n\treturn procs\n}\n\nconst colors = [\n\t'blue',\n\t'green',\n\t'yellow',\n\t'red',\n\t'magenta',\n\t'redBright',\n\t'greenBright',\n\t'yellowBright',\n\t'blueBright',\n\t'magentaBright',\n] as const\n\nfunction getNextAvailableColor(): (typeof colors)[number] {\n\tconst usedColors = new Set<(typeof colors)[number]>()\n\n\t// Collect colors used by dev processes\n\tfor (const proc of devProcesses.values()) {\n\t\tusedColors.add(proc.color)\n\t}\n\n\t// Collect colors used by sidecar processes\n\tfor (const proc of sidecarProcesses.values()) {\n\t\tusedColors.add(proc.color)\n\t}\n\n\t// Find available colors\n\tconst availableColors = colors.filter((color) => !usedColors.has(color))\n\n\tif (availableColors.length === 0) {\n\t\t// If all colors are used, cycle through them based on total process count\n\t\tconst totalProcesses = devProcesses.size + sidecarProcesses.size\n\t\treturn colors[totalProcesses % colors.length] ?? 'blue'\n\t}\n\n\t// Use the first available color\n\treturn availableColors[0] ?? 'blue'\n}\n\nexport async function runAppDev(app: App) {\n\tif (isDeployed) throw new Error('cannot run apps in deployed mode')\n\tconst key = app.name\n\t// if the app is already running, don't start it again\n\tif (devProcesses.has(key)) {\n\t\treturn { status: 'process-running', running: true } as const\n\t}\n\n\tif (app.dev.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-server' } as const\n\t}\n\n\tconst { portNumber } = app.dev\n\tif (!(await isPortAvailable(portNumber))) {\n\t\treturn { status: 'port-unavailable', running: false, portNumber } as const\n\t}\n\tconst color = getNextAvailableColor()\n\tconst appProcess = spawn('npm', ['run', 'dev', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: String(portNumber),\n\t\t\tAPP_SERVER_PORT: String(portNumber),\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst prefix = chalk[color](\n\t\t`[${app.name.replace(/^exercises\\./, '')}:${portNumber}]`,\n\t)\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stderr.on('data', handleStdErrData)\n\tdevProcesses.set(key, { color, process: appProcess, port: portNumber })\n\tappProcess.on('exit', (code) => {\n\t\tappProcess.stdout.off('data', handleStdOutData)\n\t\tappProcess.stderr.off('data', handleStdErrData)\n\t\tconsole.log(`${prefix} exited (${code})`)\n\t\tdevProcesses.delete(key)\n\t})\n\n\treturn { status: 'process-started', running: true } as const\n}\n\nexport async function runAppTests(app: App) {\n\tif (isDeployed) throw new Error('cannot run tests in deployed mode')\n\tconst key = app.name\n\n\tif (app.test.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-test' } as const\n\t}\n\n\tconst testProcess = spawn('npm', ['run', 'test', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: app.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\tAPP_SERVER_PORT:\n\t\t\t\tapp.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst output: Array<OutputLine> = []\n\tconst entry: TestProcessEntry = { process: testProcess, output }\n\tfunction handleStdOutData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stdout',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stderr',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stderr.on('data', handleStdErrData)\n\ttestProcess.on('exit', (code) => {\n\t\ttestProcess.stdout.off('data', handleStdOutData)\n\t\ttestProcess.stderr.off('data', handleStdErrData)\n\t\tentry.process = null\n\t\tentry.exitCode = code\n\t})\n\ttestProcesses.set(key, entry)\n\treturn testProcess\n}\n\nexport async function waitOnApp(app: App) {\n\tif (app.dev.type === 'script') {\n\t\tconst startTime = Date.now()\n\n\t\tconst retryInterval = 100\n\t\tconst timeout = 20_000\n\t\tlet lastError: unknown\n\t\twhile (Date.now() - startTime < timeout) {\n\t\t\ttry {\n\t\t\t\tconst url = getWorkshopUrl(app.dev.portNumber)\n\t\t\t\tawait fetch(url, {\n\t\t\t\t\tmethod: 'HEAD',\n\t\t\t\t\theaders: { Accept: '*/*' },\n\t\t\t\t})\n\t\t\t\treturn { status: 'success' } as const\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, retryInterval))\n\t\t\t}\n\t\t}\n\n\t\treturn { status: 'error', error: getErrorMessage(lastError) } as const\n\t}\n\treturn null\n}\n\nexport function isPortAvailable(port: number | string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\t\tserver.unref()\n\t\tserver.on('error', () => resolve(false))\n\n\t\tserver.listen(Number(port), () => {\n\t\t\tserver.close(() => {\n\t\t\t\tresolve(true)\n\t\t\t})\n\t\t})\n\t})\n}\n\nexport async function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess?.process.pid) return false\n\t\t// @ts-ignore - find-process is not typed correctly\n\t\t// https://github.com/yibn2008/find-process/issues/85\n\t\tconst found = await findProcess('pid', devProcess.process.pid)\n\t\treturn found.length > 0\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function isTestRunning(app: { name: string }) {\n\ttry {\n\t\tconst testProcess = testProcesses.get(app.name)\n\t\tif (!testProcess) return false\n\t\tif (testProcess.process === null) return false\n\t\ttestProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function getTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.get(app.name)\n}\n\nexport function clearTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.delete(app.name)\n}\n\nexport function getProcesses() {\n\treturn { devProcesses, testProcesses, sidecarProcesses }\n}\n\nexport function startSidecarProcesses(processes: Record<string, string>) {\n\tif (isDeployed) {\n\t\tconsole.log('Sidecar processes are not supported in deployed mode')\n\t\treturn\n\t}\n\n\tfor (const [name, command] of Object.entries(processes)) {\n\t\tstartSidecarProcess(name, command)\n\t}\n}\n\nexport function startSidecarProcess(name: string, command: string) {\n\tif (isDeployed)\n\t\tthrow new Error('cannot run sidecar processes in deployed mode')\n\n\t// if the process is already running, don't start it again\n\tif (sidecarProcesses.has(name)) {\n\t\tconsole.log(`Sidecar process ${name} is already running`)\n\t\treturn\n\t}\n\n\tconst color = getNextAvailableColor()\n\n\t// Spawn the command using shell to handle complex commands properly\n\tconst workshopRoot = getEnv().EPICSHOP_CONTEXT_CWD\n\tconst sidecarProcess = spawn(command, [], {\n\t\tshell: true,\n\t\tcwd: workshopRoot,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\tNODE_ENV: 'development',\n\t\t},\n\t})\n\n\tconst prefix = chalk[color](`[${name}]`)\n\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tsidecarProcess.stdout?.on('data', handleStdOutData)\n\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tsidecarProcess.stderr?.on('data', handleStdErrData)\n\n\tsidecarProcesses.set(name, { color, process: sidecarProcess })\n\n\tsidecarProcess.on('exit', (code: number | null, signal: string | null) => {\n\t\tsidecarProcess.stdout?.off('data', handleStdOutData)\n\t\tsidecarProcess.stderr?.off('data', handleStdErrData)\n\t\tif (code === 0) {\n\t\t\tconsole.log(`${prefix} exited successfully`)\n\t\t} else {\n\t\t\tconsole.log(\n\t\t\t\t`${prefix} exited with code ${code}${signal ? ` (signal: ${signal})` : ''}`,\n\t\t\t)\n\t\t}\n\t\tsidecarProcesses.delete(name)\n\t})\n\n\tsidecarProcess.on('error', (error) => {\n\t\tconsole.error(`${prefix} failed to start: ${error.message}`)\n\t\tsidecarProcesses.delete(name)\n\t})\n\n\tconsole.log(`${prefix} started`)\n}\n\nexport function stopSidecarProcesses() {\n\tif (isDeployed)\n\t\tthrow new Error('cannot stop sidecar processes in deployed mode')\n\n\tfor (const [name, proc] of sidecarProcesses.entries()) {\n\t\tconsole.log(`Stopping sidecar process: ${name}`)\n\t\tproc.process.kill()\n\t}\n\tsidecarProcesses.clear()\n}\n\nexport async function closeProcess(key: string) {\n\tif (isDeployed) throw new Error('cannot close processes in deployed mode')\n\tconst proc = devProcesses.get(key)\n\tif (proc) {\n\t\tconst exitedPromise = new Promise((resolve) =>\n\t\t\tproc.process.on('exit', resolve),\n\t\t)\n\t\tif (process.platform === 'win32') {\n\t\t\tconst { execa } = await import('execa')\n\t\t\ttry {\n\t\t\t\tawait execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/t'])\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`Failed to taskkill process ${proc.process.pid}:`, err)\n\t\t\t}\n\t\t} else {\n\t\t\tproc.process.kill()\n\t\t}\n\t\tawait Promise.race([\n\t\t\tnew Promise((resolve) => setTimeout(resolve, 500)),\n\t\t\texitedPromise,\n\t\t])\n\t\tawait stopPort(proc.port) // just in case 🤷‍♂️\n\t\tdevProcesses.delete(key)\n\t}\n}\n\nconst sleep = (t: number) => new Promise((resolve) => setTimeout(resolve, t))\n\nexport async function stopPort(port: string | number) {\n\tif (isDeployed) throw new Error('cannot stop ports in deployed mode')\n\tawait fkill(`:${port}`, { force: true, silent: true })\n\tawait waitForPortToBeAvailable(port)\n}\n\nexport async function waitForPortToBeAvailable(port: string | number) {\n\t// wait for the port to become available again\n\tconst timeout = Date.now() + 10_000\n\tlet portAvailable = false\n\tdo {\n\t\tportAvailable = await isPortAvailable(port)\n\t\tawait sleep(100)\n\t} while (!portAvailable && Date.now() < timeout)\n\tif (!portAvailable) {\n\t\tconsole.error('Timed out waiting for the port to become available')\n\t}\n}\n"]}
@@ -4,7 +4,7 @@ export declare function getUserId({ request }: {
4
4
  readonly id: string;
5
5
  readonly type: "cookie.clientId";
6
6
  } | {
7
- readonly id: string;
7
+ readonly id: `${string}-${string}-${string}-${string}-${string}`;
8
8
  readonly type: "cookie.randomId";
9
9
  } | {
10
10
  readonly id: string;
@@ -1,6 +1,6 @@
1
1
  // eslint-disable-next-line import/order -- this must be first
2
2
  import { getEnv } from './init-env.js';
3
- import { createId as cuid } from '@paralleldrive/cuid2';
3
+ import { randomUUID as cuid } from 'crypto';
4
4
  import * as cookie from 'cookie';
5
5
  import { getAuthInfo, getClientId } from './db.server.js';
6
6
  export async function getUserId({ request }) {
@@ -1 +1 @@
1
- {"version":3,"file":"user.server.js","sourceRoot":"","sources":["../../src/user.server.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtC,OAAO,EAAE,QAAQ,IAAI,IAAI,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAE,OAAO,EAAwB;IAChE,IAAI,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAClD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;QAEpD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YAC1B,OAAO;gBACN,EAAE,EAAE,WAAW,CAAC,QAAQ;gBACxB,IAAI,EAAE,iBAAiB;aACd,CAAA;QACX,CAAC;aAAM,CAAC;YACP,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;YACpB,OAAO;gBACN,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,iBAAiB;aACd,CAAA;QACX,CAAC;IACF,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;IAEpC,IAAI,QAAQ,EAAE,EAAE,EAAE,CAAC;QAClB,OAAO;YACN,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,aAAa;SACV,CAAA;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;IACpC,OAAO;QACN,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,aAAa;KACV,CAAA;AACX,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IAC1D,OAAO,YAAY,QAAQ,kCAAkC,CAAA;AAC9D,CAAC","sourcesContent":["// eslint-disable-next-line import/order -- this must be first\nimport { getEnv } from './init-env.js'\n\nimport { createId as cuid } from '@paralleldrive/cuid2'\nimport * as cookie from 'cookie'\nimport { getAuthInfo, getClientId } from './db.server.js'\n\nexport async function getUserId({ request }: { request: Request }) {\n\tif (getEnv().EPICSHOP_DEPLOYED) {\n\t\tconst cookieHeader = request.headers.get('cookie')\n\t\tconst cookieValue = cookie.parse(cookieHeader ?? '')\n\n\t\tif (cookieValue.clientId) {\n\t\t\treturn {\n\t\t\t\tid: cookieValue.clientId,\n\t\t\t\ttype: 'cookie.clientId',\n\t\t\t} as const\n\t\t} else {\n\t\t\tconst newId = cuid()\n\t\t\treturn {\n\t\t\t\tid: newId,\n\t\t\t\ttype: 'cookie.randomId',\n\t\t\t} as const\n\t\t}\n\t}\n\n\tconst authInfo = await getAuthInfo()\n\n\tif (authInfo?.id) {\n\t\treturn {\n\t\t\tid: authInfo.id,\n\t\t\ttype: 'db.authInfo',\n\t\t} as const\n\t}\n\n\tconst clientId = await getClientId()\n\treturn {\n\t\tid: clientId,\n\t\ttype: 'db.clientId',\n\t} as const\n}\n\nexport function getSetClientIdCookieHeader(clientId: string) {\n\treturn `clientId=${clientId}; Path=/; HttpOnly; SameSite=Lax`\n}\n"]}
1
+ {"version":3,"file":"user.server.js","sourceRoot":"","sources":["../../src/user.server.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtC,OAAO,EAAE,UAAU,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAE,OAAO,EAAwB;IAChE,IAAI,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAClD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;QAEpD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YAC1B,OAAO;gBACN,EAAE,EAAE,WAAW,CAAC,QAAQ;gBACxB,IAAI,EAAE,iBAAiB;aACd,CAAA;QACX,CAAC;aAAM,CAAC;YACP,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;YACpB,OAAO;gBACN,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,iBAAiB;aACd,CAAA;QACX,CAAC;IACF,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;IAEpC,IAAI,QAAQ,EAAE,EAAE,EAAE,CAAC;QAClB,OAAO;YACN,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,aAAa;SACV,CAAA;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;IACpC,OAAO;QACN,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,aAAa;KACV,CAAA;AACX,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IAC1D,OAAO,YAAY,QAAQ,kCAAkC,CAAA;AAC9D,CAAC","sourcesContent":["// eslint-disable-next-line import/order -- this must be first\nimport { getEnv } from './init-env.js'\n\nimport { randomUUID as cuid } from 'crypto'\nimport * as cookie from 'cookie'\nimport { getAuthInfo, getClientId } from './db.server.js'\n\nexport async function getUserId({ request }: { request: Request }) {\n\tif (getEnv().EPICSHOP_DEPLOYED) {\n\t\tconst cookieHeader = request.headers.get('cookie')\n\t\tconst cookieValue = cookie.parse(cookieHeader ?? '')\n\n\t\tif (cookieValue.clientId) {\n\t\t\treturn {\n\t\t\t\tid: cookieValue.clientId,\n\t\t\t\ttype: 'cookie.clientId',\n\t\t\t} as const\n\t\t} else {\n\t\t\tconst newId = cuid()\n\t\t\treturn {\n\t\t\t\tid: newId,\n\t\t\t\ttype: 'cookie.randomId',\n\t\t\t} as const\n\t\t}\n\t}\n\n\tconst authInfo = await getAuthInfo()\n\n\tif (authInfo?.id) {\n\t\treturn {\n\t\t\tid: authInfo.id,\n\t\t\ttype: 'db.authInfo',\n\t\t} as const\n\t}\n\n\tconst clientId = await getClientId()\n\treturn {\n\t\tid: clientId,\n\t\ttype: 'db.clientId',\n\t} as const\n}\n\nexport function getSetClientIdCookieHeader(clientId: string) {\n\treturn `clientId=${clientId}; Path=/; HttpOnly; SameSite=Lax`\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epic-web/workshop-utils",
3
- "version": "6.40.2",
3
+ "version": "6.41.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -200,64 +200,63 @@
200
200
  "@epic-web/invariant": "^1.0.0",
201
201
  "@epic-web/remember": "^1.1.0",
202
202
  "@kentcdodds/md-temp": "^10.0.1",
203
- "@mdx-js/mdx": "^3.1.0",
204
- "@paralleldrive/cuid2": "^2.2.2",
205
- "@playwright/test": "^1.53.2",
206
- "@react-router/node": "^7.8.2",
207
- "@sentry/react-router": "^10.10.0",
208
- "@testing-library/dom": "^10.4.0",
209
- "@testing-library/jest-dom": "^6.6.3",
203
+ "@mdx-js/mdx": "^3.1.1",
204
+ "@playwright/test": "^1.56.1",
205
+ "@react-router/node": "^7.9.4",
206
+ "@sentry/react-router": "^10.22.0",
207
+ "@testing-library/dom": "^10.4.1",
208
+ "@testing-library/jest-dom": "^6.9.1",
210
209
  "@total-typescript/ts-reset": "^0.6.1",
211
- "@types/chai": "^5.2.2",
210
+ "@types/chai": "^5.2.3",
212
211
  "@types/chai-dom": "^1.11.3",
213
- "@vitest/expect": "^3.2.4",
214
- "chai": "^5.2.0",
212
+ "@vitest/expect": "^4.0.3",
213
+ "chai": "^6.2.0",
215
214
  "chai-dom": "^1.12.1",
216
- "chalk": "^5.4.1",
215
+ "chalk": "^5.6.2",
217
216
  "chokidar": "^4.0.3",
218
- "close-with-grace": "^2.2.0",
217
+ "close-with-grace": "^2.3.0",
219
218
  "cookie": "^1.0.2",
220
219
  "cross-spawn": "^7.0.6",
221
- "dayjs": "^1.11.13",
222
- "esbuild": "^0.25.5",
220
+ "dayjs": "^1.11.18",
221
+ "esbuild": "^0.25.11",
223
222
  "execa": "^9.6.0",
224
- "find-process": "^1.4.10",
223
+ "find-process": "^2.0.0",
225
224
  "fkill": "^9.0.0",
226
- "fs-extra": "^11.3.0",
227
- "globby": "^14.1.0",
225
+ "fs-extra": "^11.3.2",
226
+ "globby": "^15.0.0",
228
227
  "ignore": "^7.0.5",
229
228
  "json5": "^2.2.3",
230
- "lru-cache": "^11.1.0",
229
+ "lru-cache": "^11.2.2",
231
230
  "lz-string": "^1.5.0",
232
231
  "md5-hex": "^5.0.0",
233
232
  "mdast-util-mdx-jsx": "^3.2.0",
234
233
  "mdx-bundler": "^10.1.1",
235
- "p-queue": "^8.1.0",
234
+ "p-queue": "^9.0.0",
236
235
  "parse-git-diff": "^0.0.19",
237
- "react": "^19.1.0",
238
- "react-dom": "^19.1.0",
239
- "react-router": "npm:@kentcdodds/tmp_react-router@7.8.2-patched.2",
236
+ "react": "^19.2.0",
237
+ "react-dom": "^19.2.0",
238
+ "react-router": "^7.9.4",
240
239
  "rehype": "^13.0.2",
241
240
  "rehype-autolink-headings": "^7.1.0",
242
241
  "remark": "^15.0.1",
243
- "remark-emoji": "^5.0.1",
242
+ "remark-emoji": "^5.0.2",
244
243
  "remark-gfm": "^4.0.1",
245
244
  "shell-quote": "^1.8.3",
246
- "shiki": "^3.7.0",
245
+ "shiki": "^3.13.0",
247
246
  "unified": "^11.0.5",
248
247
  "unist-util-remove-position": "^5.0.0",
249
248
  "unist-util-visit": "^5.0.0",
250
- "zod": "^3.25.71"
249
+ "zod": "^3.25.76"
251
250
  },
252
251
  "devDependencies": {
253
252
  "@types/hast": "^3.0.4",
254
253
  "@types/mdast": "^4.0.4",
255
- "@types/node": "^24.0.10",
256
- "@types/react": "^19.1.8",
257
- "@types/react-dom": "^19.1.6",
254
+ "@types/node": "^24.9.1",
255
+ "@types/react": "^19.2.2",
256
+ "@types/react-dom": "^19.2.2",
258
257
  "@types/shell-quote": "^1.7.5",
259
- "tshy": "^3.0.2",
260
- "vitest": "^3.2.4"
258
+ "tshy": "^3.0.3",
259
+ "vitest": "^4.0.3"
261
260
  },
262
261
  "repository": {
263
262
  "type": "git",