@epic-web/workshop-utils 4.4.0 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/apps.server.d.ts +115 -35
- package/dist/esm/apps.server.d.ts.map +1 -1
- package/dist/esm/apps.server.js +3 -7
- package/dist/esm/apps.server.js.map +1 -1
- package/dist/esm/cache.server.d.ts.map +1 -1
- package/dist/esm/cache.server.js +0 -1
- package/dist/esm/cache.server.js.map +1 -1
- package/dist/esm/codefile-mdx.server.d.ts.map +1 -1
- package/dist/esm/codefile-mdx.server.js +1 -2
- package/dist/esm/codefile-mdx.server.js.map +1 -1
- package/dist/esm/compile-mdx.server.d.ts.map +1 -1
- package/dist/esm/compile-mdx.server.js +1 -2
- package/dist/esm/compile-mdx.server.js.map +1 -1
- package/dist/esm/db.server.d.ts +6 -6
- package/dist/esm/iframe-sync.d.ts.map +1 -1
- package/dist/esm/iframe-sync.js +0 -4
- package/dist/esm/iframe-sync.js.map +1 -1
- package/dist/esm/playwright.server.d.ts.map +1 -1
- package/dist/esm/playwright.server.js +1 -2
- package/dist/esm/playwright.server.js.map +1 -1
- package/dist/esm/process-manager.server.d.ts +14 -2
- package/dist/esm/process-manager.server.d.ts.map +1 -1
- package/dist/esm/process-manager.server.js.map +1 -1
- package/dist/esm/test.d.ts.map +1 -1
- package/dist/esm/test.js +0 -1
- package/dist/esm/test.js.map +1 -1
- package/dist/esm/timing.server.d.ts.map +1 -1
- package/dist/esm/timing.server.js +0 -2
- package/dist/esm/timing.server.js.map +1 -1
- package/dist/esm/utils.server.d.ts.map +1 -1
- package/dist/esm/utils.server.js +0 -1
- package/dist/esm/utils.server.js.map +1 -1
- package/package.json +16 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codefile-mdx.server.js","sourceRoot":"","sources":["../../src/codefile-mdx.server.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { createProcessor } from '@mdx-js/mdx'\nimport md5 from 'md5-hex'\nimport { type RootContent, type Root as MdastRoot, type Parent } from 'mdast'\nimport {\n\ttype MdxJsxAttribute,\n\ttype MdxJsxFlowElement,\n} from 'mdast-util-mdx-jsx'\nimport { removePosition } from 'unist-util-remove-position'\nimport { type Visitor, visit } from 'unist-util-visit'\nimport * as z from 'zod'\n\ntype CodeFile = {\n\tnode: MdxJsxFlowElement\n\tparent: Parent | null | undefined\n}\n\ntype RangeArray = [number, number][] | undefined\n\ntype CodeFileProps = Record<string, unknown>\n\ntype PathContentMap = Map<string, string[]>\n\nconst APP_TYPES = ['problem', 'solution', 'playground'] as const\ntype AppTypes = typeof APP_TYPES\n\nexport type EmbeddedFile = {\n\terror?: boolean\n\tfile: string\n\thash: string\n\tline?: number\n\twarning?: string\n}\n\nexport type CodeFileData = {\n\tmdxFile: string\n\tcacheLocation: string\n\tcachedEmbeddedFiles: Map<string, EmbeddedFile>\n\tembeddedFiles: Map<string, EmbeddedFile>\n}\n\nconst safePath = (s: string) => s.replace(/\\\\/g, '/')\n\nconst REG_EXP = /^(?:\\d+(?:-\\d+)?,)*\\d+(?:-\\d+)?$/\n\nconst isValidRangeFormat = (value: string | undefined) =>\n\tvalue ? REG_EXP.test(value) : true\n\nconst transformRange = (value: string | undefined) =>\n\tvalue?.split(',').map(range => {\n\t\tconst [start, end] = range.split('-').map(Number)\n\t\treturn [start, end ?? start] as [number, number]\n\t})\n\nconst isRangeBounded = (\n\trange: RangeArray,\n\tctx: z.RefinementCtx,\n\tlines: number,\n) => {\n\tif (!lines || !Array.isArray(range)) return\n\tif (range.flat().some(r => r < 1 || r > lines)) {\n\t\tctx.addIssue({\n\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\tmessage: `Range must be between 1 and ${lines}`,\n\t\t})\n\t}\n}\n\nconst isRangeInOrder = (range: RangeArray) =>\n\tArray.isArray(range)\n\t\t? range.every(([a, b]) => !isNaN(Number(a)) && !isNaN(Number(b)) && b >= a)\n\t\t: true\n\nconst isRangesNonOverlapping = (range: RangeArray) => {\n\tif (!Array.isArray(range)) return true\n\treturn range.every(([a], i) => i === 0 || (range[i - 1]?.[1] ?? 0) < a)\n}\n\nlet fileContentCache: PathContentMap = new Map()\nasync function getFileContent(filePath: string) {\n\tif (fileContentCache.has(filePath)) {\n\t\treturn fileContentCache.get(filePath)\n\t}\n\ttry {\n\t\tconst content = await fs.promises.readFile(filePath, 'utf-8')\n\t\tconst fileContent = content.split('\\n')\n\t\tfileContentCache.set(filePath, fileContent)\n\t\treturn fileContent\n\t} catch (error) {\n\t\tconsole.warn(\n\t\t\t`@epic-web/workshop-app - invalid CodeFile.\\nCould not read file: ${filePath}\\n`,\n\t\t)\n\t}\n}\n\nasync function validateProps(props: CodeFileProps, appDir: string) {\n\tlet validRange: RangeArray\n\tlet linesCount = 0\n\n\tconst BooleanSchema = z\n\t\t.nullable(z.string())\n\t\t.optional()\n\t\t.refine(\n\t\t\tv => ['true', 'false', null, undefined].includes(v),\n\t\t\t'optional boolean key can be \"true\", \"false\", null or undefined',\n\t\t)\n\t\t.transform(v => v === null || Boolean(v))\n\n\tconst RangeSchema = z\n\t\t.string()\n\t\t.optional()\n\t\t.refine(isValidRangeFormat, 'Invalid range format')\n\t\t.transform(transformRange)\n\t\t.superRefine((val, ctx) => isRangeBounded(val, ctx, linesCount))\n\t\t.refine(isRangeInOrder, 'Range must be in order low-high')\n\n\tconst inputSchema = z\n\t\t.object({\n\t\t\tfile: z\n\t\t\t\t.string()\n\t\t\t\t.nonempty()\n\t\t\t\t.transform(async (file, ctx) => {\n\t\t\t\t\tconst fullPath = path.join(appDir, file)\n\t\t\t\t\tconst content = await getFileContent(fullPath)\n\t\t\t\t\tif (!content) {\n\t\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\t\t\tmessage: `Could not read file`,\n\t\t\t\t\t\t\tfatal: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn z.NEVER\n\t\t\t\t\t}\n\t\t\t\t\tlinesCount = content.length\n\t\t\t\t\t// @mdx-js/mdx parser can NOT handle relative path with backslashes\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfullPath: safePath(fullPath),\n\t\t\t\t\t\tfilePath: safePath(file),\n\t\t\t\t\t\tcontent,\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\trange: RangeSchema.refine(range => {\n\t\t\t\tconst isValid = isRangesNonOverlapping(range)\n\t\t\t\t// we use this value in highlight refine\n\t\t\t\tvalidRange = isValid ? range : undefined\n\t\t\t\treturn isValid\n\t\t\t}, 'Ranges must not overlap'),\n\t\t\thighlight: RangeSchema.refine(highlight => {\n\t\t\t\tif (!Array.isArray(highlight) || !Array.isArray(validRange)) {\n\t\t\t\t\treturn z.NEVER\n\t\t\t\t}\n\t\t\t\treturn highlight.every(([hStart, hEnd]) =>\n\t\t\t\t\tvalidRange?.some(\n\t\t\t\t\t\t([rStart, rEnd]) => hStart >= rStart && hEnd <= rEnd,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}, 'Highlight range must be within defined range')\n\t\t\t\t.transform(() => props.highlight as Array<string>)\n\t\t\t\t.optional(),\n\t\t\tnonumber: BooleanSchema,\n\t\t\tnocopy: BooleanSchema,\n\t\t\tbuttons: z\n\t\t\t\t.string()\n\t\t\t\t.optional()\n\t\t\t\t.transform(str => (str ? (str.split(',') as unknown as AppTypes) : []))\n\t\t\t\t.refine(arr => arr.every(item => APP_TYPES.includes(item)), {\n\t\t\t\t\tmessage: `Buttons can only be any of ${APP_TYPES.join(',')}`,\n\t\t\t\t}),\n\t\t})\n\t\t.strict()\n\n\treturn inputSchema.safeParseAsync(props)\n}\n\nasync function createErrorNotification(\n\tnode: MdxJsxFlowElement,\n\terrors: string[],\n\tmdxFile: string,\n\tappType: string,\n) {\n\tconst filename = path.basename(mdxFile)\n\tconst startLine = node.position?.start.line\n\tconst endLine = node.position?.end.line\n\n\tconst codeFence = async () => {\n\t\tif (startLine && endLine) {\n\t\t\tconst contentStr = await getFileContent(mdxFile)\n\t\t\tconst content = contentStr?.slice(startLine - 1, endLine).join('\\n')\n\t\t\tif (content) {\n\t\t\t\treturn `\n\\`\\`\\`tsx filename=${filename} start=${startLine} nocopy\n${content}\n\\`\\`\\``.trim()\n\t\t\t}\n\t\t}\n\t\treturn ''\n\t}\n\n\tconst mdxSource = `\n<CodeFileNotification variant=\"error\" file=\"${filename}\" line=\"${startLine}\" type=\"${appType}\">\n <callout-danger class=\"notification\">\n <div className=\"title\">CodeFile Error: invalid input</div>\n ${errors.map(error => `<div>${error}</div>`).join('')}\n${await codeFence()}\n </callout-danger>\n</CodeFileNotification>`\n\n\treturn mdxToMdast(mdxSource)\n}\n\n// based on https://github.com/sindresorhus/strip-indent\nfunction stripIndent(string: string) {\n\tconst match = string.match(/^[ \\t]*(?=\\S)/gm)\n\tconst indent = match?.reduce((r, a) => Math.min(r, a.length), Infinity) ?? 0\n\tif (indent === 0) {\n\t\treturn string\n\t}\n\tconst regex = new RegExp(`^[ \\\\t]{${indent}}`, 'gm')\n\treturn string.replace(regex, '')\n}\n\nfunction mdxToMdast(mdx: string) {\n\tconst processor = createProcessor()\n\tconst mdast = processor.parse(mdx.trim()) as MdastRoot | RootContent\n\tremovePosition(mdast, { force: true })\n\treturn mdast.type === 'root' ? mdast.children : [mdast]\n}\n\nexport function remarkCodeFile(data: CodeFileData) {\n\tfileContentCache = new Map()\n\tconst mdxFile = data.mdxFile\n\tconst appDir = path.dirname(mdxFile)\n\tconst appType = mdxFile.includes('problem')\n\t\t? 'problem'\n\t\t: mdxFile.includes('solution')\n\t\t\t? 'solution'\n\t\t\t: 'other' // not in exercise\n\n\tasync function replaceCodeFileNode({\n\t\tnode,\n\t\tparent,\n\t}: CodeFile): Promise<void> {\n\t\tif (!parent) {\n\t\t\tconsole.warn(\n\t\t\t\t'Unexpected error: replaceCodeFileNode called without a Parent',\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tconst index = parent.children.indexOf(node)\n\t\tif (index === -1) {\n\t\t\tconsole.warn(\n\t\t\t\t'Unexpected error: replaceCodeFileNode could not find node index in Parent',\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tconst attributes = node.attributes as MdxJsxAttribute[]\n\t\tconst props: CodeFileProps = {}\n\t\tfor (const { name, value } of attributes) {\n\t\t\tprops[name] = value\n\t\t}\n\n\t\tconst result = await validateProps(props, appDir)\n\t\tif (!result.success) {\n\t\t\tconst errors = result.error.issues.map(({ message, path }) =>\n\t\t\t\tpath[0] ? `${message}: ${path[0]}=\"${props[path[0]]}\"` : message,\n\t\t\t)\n\t\t\tconst notification = await createErrorNotification(\n\t\t\t\tnode,\n\t\t\t\terrors,\n\t\t\t\tmdxFile,\n\t\t\t\tappType,\n\t\t\t)\n\t\t\tparent.children.splice(index, 1, ...notification)\n\n\t\t\tdata.embeddedFiles.set('invalid input', {\n\t\t\t\terror: true,\n\t\t\t\tfile: props.file as string,\n\t\t\t\thash: '',\n\t\t\t\tline: node.position?.start.line ?? 1,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst {\n\t\t\tfile: { content, filePath, fullPath },\n\t\t\thighlight,\n\t\t\trange,\n\t\t} = result.data\n\t\tconst language = path.extname(filePath).substring(1)\n\t\tconst meta = [`filename=${filePath}`]\n\n\t\t// nonumbers nocopy ....\n\t\tObject.entries(result.data).forEach(\n\t\t\t([key, val]) =>\n\t\t\t\ttypeof val === 'boolean' && val && meta.push(`${key}=true`),\n\t\t)\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\t\tif (result.data.buttons) {\n\t\t\tmeta.push(`buttons=${result.data.buttons.join(',')}`)\n\t\t\tmeta.push(`type=${appType}`)\n\t\t\tmeta.push(`fullpath=${fullPath}`)\n\t\t\t// Avoid the headache of finding the separator on the client side\n\t\t\t// path.sep is always / on client side\n\t\t\tmeta.push(`sep=${path.sep}`)\n\t\t}\n\n\t\tif (highlight?.length) {\n\t\t\tmeta.push(`lines=${highlight}`)\n\t\t}\n\n\t\tconst fileSections = range?.length ? range : [[1, content.length]]\n\t\tconst rangesContent = []\n\t\tconst preNodes = []\n\t\tfor (const [start, end] of fileSections) {\n\t\t\tconst rangeContent = stripIndent(\n\t\t\t\tcontent.slice(start ? start - 1 : 0, end).join('\\n'),\n\t\t\t)\n\t\t\trangesContent.push(rangeContent)\n\t\t\tconst mdxSource = `\n\\`\\`\\`${language} ${meta.concat(`start=${start}`).join(' ')}\n${rangeContent}\n\\`\\`\\``\n\t\t\tpreNodes.push(...mdxToMdast(mdxSource))\n\t\t}\n\n\t\t/**\n\t\t * Show a warning above the file content if the range we show changed in the\n\t\t * embedded file and the range in <CodeFile range=\"a-b\"> did not change.\n\t\t * The warning will be removed automatically after the <CodeFile> range changes\n\t\t * or by canceling it from the UI.\n\t\t */\n\t\tconst embeddedKey = md5(fullPath + JSON.stringify(range))\n\t\tconst contentHash = md5(rangesContent.join(','))\n\t\tconst newData: EmbeddedFile = {\n\t\t\tfile: fullPath,\n\t\t\thash: contentHash,\n\t\t}\n\t\tconst cachedData = data.cachedEmbeddedFiles.get(embeddedKey)\n\n\t\tif (\n\t\t\tcachedData &&\n\t\t\t// If a warning existed previously and its hash matched the current hash,\n\t\t\t// then the changes were reverted and the warning will be remove\n\t\t\t((cachedData.warning && cachedData.warning !== contentHash) ??\n\t\t\t\t(!cachedData.warning && cachedData.hash !== contentHash))\n\t\t) {\n\t\t\t// keep previously saved warning or previous hash\n\t\t\tnewData.warning = cachedData.warning ?? cachedData.hash\n\t\t\tconst startLine = node.position?.start.line ?? 1\n\t\t\tnewData.line = startLine\n\t\t\tconst mdxFilename = path.basename(mdxFile)\n\t\t\tconst filename = path.basename(filePath)\n\t\t\tconst warning = `\n<CodeFileNotification variant=\"warning\" file=\"${mdxFilename}\" line=\"${startLine}\" type=\"${appType}\"\ncacheLocation=\"${data.cacheLocation}\" embeddedKey=\"${embeddedKey}\">\n <callout-warning class=\"notification\">\n <div className=\"title\">CodeFile Warning:</div>\n <div>file ${filename} content was changed, review 'range' and 'highlight' inputs</div>\n </callout-warning>\n</CodeFileNotification>`\n\t\t\tpreNodes.unshift(...mdxToMdast(warning))\n\t\t}\n\t\tdata.embeddedFiles.set(embeddedKey, newData)\n\n\t\t// replace <CodeFile> with embedded file content\n\t\tparent.children.splice(index, 1, ...preNodes)\n\t}\n\n\treturn async function codeFileTransformer(tree: MdastRoot) {\n\t\tconst codeFiles: CodeFile[] = []\n\t\tconst filter = { type: 'mdxJsxFlowElement', name: 'CodeFile' } as const\n\t\tvisit<MdastRoot, typeof filter>(tree, filter, ((node, _index, parent) => {\n\t\t\tcodeFiles.push({ node, parent })\n\t\t}) as Visitor<MdxJsxFlowElement, Parent>)\n\n\t\tfor (const props of codeFiles) {\n\t\t\tawait replaceCodeFileNode(props)\n\t\t}\n\n\t\t// cleanup\n\t\tfileContentCache = new Map()\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"codefile-mdx.server.js","sourceRoot":"","sources":["../../src/codefile-mdx.server.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { createProcessor } from '@mdx-js/mdx'\nimport md5 from 'md5-hex'\nimport { type Root as MdastRoot, type Parent, type RootContent } from 'mdast'\nimport {\n\ttype MdxJsxAttribute,\n\ttype MdxJsxFlowElement,\n} from 'mdast-util-mdx-jsx'\nimport { removePosition } from 'unist-util-remove-position'\nimport { visit, type Visitor } from 'unist-util-visit'\nimport * as z from 'zod'\n\ntype CodeFile = {\n\tnode: MdxJsxFlowElement\n\tparent: Parent | null | undefined\n}\n\ntype RangeArray = [number, number][] | undefined\n\ntype CodeFileProps = Record<string, unknown>\n\ntype PathContentMap = Map<string, string[]>\n\nconst APP_TYPES = ['problem', 'solution', 'playground'] as const\ntype AppTypes = typeof APP_TYPES\n\nexport type EmbeddedFile = {\n\terror?: boolean\n\tfile: string\n\thash: string\n\tline?: number\n\twarning?: string\n}\n\nexport type CodeFileData = {\n\tmdxFile: string\n\tcacheLocation: string\n\tcachedEmbeddedFiles: Map<string, EmbeddedFile>\n\tembeddedFiles: Map<string, EmbeddedFile>\n}\n\nconst safePath = (s: string) => s.replace(/\\\\/g, '/')\n\nconst REG_EXP = /^(?:\\d+(?:-\\d+)?,)*\\d+(?:-\\d+)?$/\n\nconst isValidRangeFormat = (value: string | undefined) =>\n\tvalue ? REG_EXP.test(value) : true\n\nconst transformRange = (value: string | undefined) =>\n\tvalue?.split(',').map(range => {\n\t\tconst [start, end] = range.split('-').map(Number)\n\t\treturn [start, end ?? start] as [number, number]\n\t})\n\nconst isRangeBounded = (\n\trange: RangeArray,\n\tctx: z.RefinementCtx,\n\tlines: number,\n) => {\n\tif (!lines || !Array.isArray(range)) return\n\tif (range.flat().some(r => r < 1 || r > lines)) {\n\t\tctx.addIssue({\n\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\tmessage: `Range must be between 1 and ${lines}`,\n\t\t})\n\t}\n}\n\nconst isRangeInOrder = (range: RangeArray) =>\n\tArray.isArray(range)\n\t\t? range.every(([a, b]) => !isNaN(Number(a)) && !isNaN(Number(b)) && b >= a)\n\t\t: true\n\nconst isRangesNonOverlapping = (range: RangeArray) => {\n\tif (!Array.isArray(range)) return true\n\treturn range.every(([a], i) => i === 0 || (range[i - 1]?.[1] ?? 0) < a)\n}\n\nlet fileContentCache: PathContentMap = new Map()\nasync function getFileContent(filePath: string) {\n\tif (fileContentCache.has(filePath)) {\n\t\treturn fileContentCache.get(filePath)\n\t}\n\ttry {\n\t\tconst content = await fs.promises.readFile(filePath, 'utf-8')\n\t\tconst fileContent = content.split('\\n')\n\t\tfileContentCache.set(filePath, fileContent)\n\t\treturn fileContent\n\t} catch {\n\t\tconsole.warn(\n\t\t\t`@epic-web/workshop-app - invalid CodeFile.\\nCould not read file: ${filePath}\\n`,\n\t\t)\n\t}\n}\n\nasync function validateProps(props: CodeFileProps, appDir: string) {\n\tlet validRange: RangeArray\n\tlet linesCount = 0\n\n\tconst BooleanSchema = z\n\t\t.nullable(z.string())\n\t\t.optional()\n\t\t.refine(\n\t\t\tv => ['true', 'false', null, undefined].includes(v),\n\t\t\t'optional boolean key can be \"true\", \"false\", null or undefined',\n\t\t)\n\t\t.transform(v => v === null || Boolean(v))\n\n\tconst RangeSchema = z\n\t\t.string()\n\t\t.optional()\n\t\t.refine(isValidRangeFormat, 'Invalid range format')\n\t\t.transform(transformRange)\n\t\t.superRefine((val, ctx) => isRangeBounded(val, ctx, linesCount))\n\t\t.refine(isRangeInOrder, 'Range must be in order low-high')\n\n\tconst inputSchema = z\n\t\t.object({\n\t\t\tfile: z\n\t\t\t\t.string()\n\t\t\t\t.nonempty()\n\t\t\t\t.transform(async (file, ctx) => {\n\t\t\t\t\tconst fullPath = path.join(appDir, file)\n\t\t\t\t\tconst content = await getFileContent(fullPath)\n\t\t\t\t\tif (!content) {\n\t\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\t\t\tmessage: `Could not read file`,\n\t\t\t\t\t\t\tfatal: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn z.NEVER\n\t\t\t\t\t}\n\t\t\t\t\tlinesCount = content.length\n\t\t\t\t\t// @mdx-js/mdx parser can NOT handle relative path with backslashes\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfullPath: safePath(fullPath),\n\t\t\t\t\t\tfilePath: safePath(file),\n\t\t\t\t\t\tcontent,\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\trange: RangeSchema.refine(range => {\n\t\t\t\tconst isValid = isRangesNonOverlapping(range)\n\t\t\t\t// we use this value in highlight refine\n\t\t\t\tvalidRange = isValid ? range : undefined\n\t\t\t\treturn isValid\n\t\t\t}, 'Ranges must not overlap'),\n\t\t\thighlight: RangeSchema.refine(highlight => {\n\t\t\t\tif (!Array.isArray(highlight) || !Array.isArray(validRange)) {\n\t\t\t\t\treturn z.NEVER\n\t\t\t\t}\n\t\t\t\treturn highlight.every(([hStart, hEnd]) =>\n\t\t\t\t\tvalidRange?.some(\n\t\t\t\t\t\t([rStart, rEnd]) => hStart >= rStart && hEnd <= rEnd,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}, 'Highlight range must be within defined range')\n\t\t\t\t.transform(() => props.highlight as Array<string>)\n\t\t\t\t.optional(),\n\t\t\tnonumber: BooleanSchema,\n\t\t\tnocopy: BooleanSchema,\n\t\t\tbuttons: z\n\t\t\t\t.string()\n\t\t\t\t.optional()\n\t\t\t\t.transform(str => (str ? (str.split(',') as unknown as AppTypes) : []))\n\t\t\t\t.refine(arr => arr.every(item => APP_TYPES.includes(item)), {\n\t\t\t\t\tmessage: `Buttons can only be any of ${APP_TYPES.join(',')}`,\n\t\t\t\t}),\n\t\t})\n\t\t.strict()\n\n\treturn inputSchema.safeParseAsync(props)\n}\n\nasync function createErrorNotification(\n\tnode: MdxJsxFlowElement,\n\terrors: string[],\n\tmdxFile: string,\n\tappType: string,\n) {\n\tconst filename = path.basename(mdxFile)\n\tconst startLine = node.position?.start.line\n\tconst endLine = node.position?.end.line\n\n\tconst codeFence = async () => {\n\t\tif (startLine && endLine) {\n\t\t\tconst contentStr = await getFileContent(mdxFile)\n\t\t\tconst content = contentStr?.slice(startLine - 1, endLine).join('\\n')\n\t\t\tif (content) {\n\t\t\t\treturn `\n\\`\\`\\`tsx filename=${filename} start=${startLine} nocopy\n${content}\n\\`\\`\\``.trim()\n\t\t\t}\n\t\t}\n\t\treturn ''\n\t}\n\n\tconst mdxSource = `\n<CodeFileNotification variant=\"error\" file=\"${filename}\" line=\"${startLine}\" type=\"${appType}\">\n <callout-danger class=\"notification\">\n <div className=\"title\">CodeFile Error: invalid input</div>\n ${errors.map(error => `<div>${error}</div>`).join('')}\n${await codeFence()}\n </callout-danger>\n</CodeFileNotification>`\n\n\treturn mdxToMdast(mdxSource)\n}\n\n// based on https://github.com/sindresorhus/strip-indent\nfunction stripIndent(string: string) {\n\tconst match = string.match(/^[ \\t]*(?=\\S)/gm)\n\tconst indent = match?.reduce((r, a) => Math.min(r, a.length), Infinity) ?? 0\n\tif (indent === 0) {\n\t\treturn string\n\t}\n\tconst regex = new RegExp(`^[ \\\\t]{${indent}}`, 'gm')\n\treturn string.replace(regex, '')\n}\n\nfunction mdxToMdast(mdx: string) {\n\tconst processor = createProcessor()\n\tconst mdast = processor.parse(mdx.trim()) as MdastRoot | RootContent\n\tremovePosition(mdast, { force: true })\n\treturn mdast.type === 'root' ? mdast.children : [mdast]\n}\n\nexport function remarkCodeFile(data: CodeFileData) {\n\tfileContentCache = new Map()\n\tconst mdxFile = data.mdxFile\n\tconst appDir = path.dirname(mdxFile)\n\tconst appType = mdxFile.includes('problem')\n\t\t? 'problem'\n\t\t: mdxFile.includes('solution')\n\t\t\t? 'solution'\n\t\t\t: 'other' // not in exercise\n\n\tasync function replaceCodeFileNode({\n\t\tnode,\n\t\tparent,\n\t}: CodeFile): Promise<void> {\n\t\tif (!parent) {\n\t\t\tconsole.warn(\n\t\t\t\t'Unexpected error: replaceCodeFileNode called without a Parent',\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tconst index = parent.children.indexOf(node)\n\t\tif (index === -1) {\n\t\t\tconsole.warn(\n\t\t\t\t'Unexpected error: replaceCodeFileNode could not find node index in Parent',\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tconst attributes = node.attributes as MdxJsxAttribute[]\n\t\tconst props: CodeFileProps = {}\n\t\tfor (const { name, value } of attributes) {\n\t\t\tprops[name] = value\n\t\t}\n\n\t\tconst result = await validateProps(props, appDir)\n\t\tif (!result.success) {\n\t\t\tconst errors = result.error.issues.map(({ message, path }) =>\n\t\t\t\tpath[0] ? `${message}: ${path[0]}=\"${props[path[0]]}\"` : message,\n\t\t\t)\n\t\t\tconst notification = await createErrorNotification(\n\t\t\t\tnode,\n\t\t\t\terrors,\n\t\t\t\tmdxFile,\n\t\t\t\tappType,\n\t\t\t)\n\t\t\tparent.children.splice(index, 1, ...notification)\n\n\t\t\tdata.embeddedFiles.set('invalid input', {\n\t\t\t\terror: true,\n\t\t\t\tfile: props.file as string,\n\t\t\t\thash: '',\n\t\t\t\tline: node.position?.start.line ?? 1,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst {\n\t\t\tfile: { content, filePath, fullPath },\n\t\t\thighlight,\n\t\t\trange,\n\t\t} = result.data\n\t\tconst language = path.extname(filePath).substring(1)\n\t\tconst meta = [`filename=${filePath}`]\n\n\t\t// nonumbers nocopy ....\n\t\tObject.entries(result.data).forEach(\n\t\t\t([key, val]) =>\n\t\t\t\ttypeof val === 'boolean' && val && meta.push(`${key}=true`),\n\t\t)\n\n\t\tif (result.data.buttons) {\n\t\t\tmeta.push(`buttons=${result.data.buttons.join(',')}`)\n\t\t\tmeta.push(`type=${appType}`)\n\t\t\tmeta.push(`fullpath=${fullPath}`)\n\t\t\t// Avoid the headache of finding the separator on the client side\n\t\t\t// path.sep is always / on client side\n\t\t\tmeta.push(`sep=${path.sep}`)\n\t\t}\n\n\t\tif (highlight?.length) {\n\t\t\tmeta.push(`lines=${highlight}`)\n\t\t}\n\n\t\tconst fileSections = range?.length ? range : [[1, content.length]]\n\t\tconst rangesContent = []\n\t\tconst preNodes = []\n\t\tfor (const [start, end] of fileSections) {\n\t\t\tconst rangeContent = stripIndent(\n\t\t\t\tcontent.slice(start ? start - 1 : 0, end).join('\\n'),\n\t\t\t)\n\t\t\trangesContent.push(rangeContent)\n\t\t\tconst mdxSource = `\n\\`\\`\\`${language} ${meta.concat(`start=${start}`).join(' ')}\n${rangeContent}\n\\`\\`\\``\n\t\t\tpreNodes.push(...mdxToMdast(mdxSource))\n\t\t}\n\n\t\t/**\n\t\t * Show a warning above the file content if the range we show changed in the\n\t\t * embedded file and the range in <CodeFile range=\"a-b\"> did not change.\n\t\t * The warning will be removed automatically after the <CodeFile> range changes\n\t\t * or by canceling it from the UI.\n\t\t */\n\t\tconst embeddedKey = md5(fullPath + JSON.stringify(range))\n\t\tconst contentHash = md5(rangesContent.join(','))\n\t\tconst newData: EmbeddedFile = {\n\t\t\tfile: fullPath,\n\t\t\thash: contentHash,\n\t\t}\n\t\tconst cachedData = data.cachedEmbeddedFiles.get(embeddedKey)\n\n\t\tif (\n\t\t\tcachedData &&\n\t\t\t// If a warning existed previously and its hash matched the current hash,\n\t\t\t// then the changes were reverted and the warning will be remove\n\t\t\t((cachedData.warning && cachedData.warning !== contentHash) ??\n\t\t\t\t(!cachedData.warning && cachedData.hash !== contentHash))\n\t\t) {\n\t\t\t// keep previously saved warning or previous hash\n\t\t\tnewData.warning = cachedData.warning ?? cachedData.hash\n\t\t\tconst startLine = node.position?.start.line ?? 1\n\t\t\tnewData.line = startLine\n\t\t\tconst mdxFilename = path.basename(mdxFile)\n\t\t\tconst filename = path.basename(filePath)\n\t\t\tconst warning = `\n<CodeFileNotification variant=\"warning\" file=\"${mdxFilename}\" line=\"${startLine}\" type=\"${appType}\"\ncacheLocation=\"${data.cacheLocation}\" embeddedKey=\"${embeddedKey}\">\n <callout-warning class=\"notification\">\n <div className=\"title\">CodeFile Warning:</div>\n <div>file ${filename} content was changed, review 'range' and 'highlight' inputs</div>\n </callout-warning>\n</CodeFileNotification>`\n\t\t\tpreNodes.unshift(...mdxToMdast(warning))\n\t\t}\n\t\tdata.embeddedFiles.set(embeddedKey, newData)\n\n\t\t// replace <CodeFile> with embedded file content\n\t\tparent.children.splice(index, 1, ...preNodes)\n\t}\n\n\treturn async function codeFileTransformer(tree: MdastRoot) {\n\t\tconst codeFiles: CodeFile[] = []\n\t\tconst filter = { type: 'mdxJsxFlowElement', name: 'CodeFile' } as const\n\t\tvisit<MdastRoot, typeof filter>(tree, filter, ((node, _index, parent) => {\n\t\t\tcodeFiles.push({ node, parent })\n\t\t}) as Visitor<MdxJsxFlowElement, Parent>)\n\n\t\tfor (const props of codeFiles) {\n\t\t\tawait replaceCodeFileNode(props)\n\t\t}\n\n\t\t// cleanup\n\t\tfileContentCache = new Map()\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-mdx.server.d.ts","sourceRoot":"","sources":["../../src/compile-mdx.server.ts"],"names":[],"mappings":"AAkHA,wBAAsB,UAAU,CAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACvE,OAAO,CAAC;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAC9B,CAAC,CA8HD;AAED,wBAAsB,qBAAqB,CAAC,cAAc,EAAE,MAAM,mBAuCjE;
|
|
1
|
+
{"version":3,"file":"compile-mdx.server.d.ts","sourceRoot":"","sources":["../../src/compile-mdx.server.ts"],"names":[],"mappings":"AAkHA,wBAAsB,UAAU,CAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACvE,OAAO,CAAC;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAC9B,CAAC,CA8HD;AAED,wBAAsB,qBAAqB,CAAC,cAAc,EAAE,MAAM,mBAuCjE;AAmFD,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,oBAQpD"}
|
|
@@ -239,7 +239,6 @@ async function updateEmbeddedFilesCache({ mdxFile, embeddedFiles, }) {
|
|
|
239
239
|
for (const [key, value] of Object.entries(cachedList)) {
|
|
240
240
|
cachedList[key] = value.filter(item => item !== mdxFile);
|
|
241
241
|
if (cachedList[key]?.length === 0) {
|
|
242
|
-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
243
242
|
delete cachedList[key];
|
|
244
243
|
}
|
|
245
244
|
}
|
|
@@ -284,7 +283,7 @@ async function getEmbeddedFilesCache() {
|
|
|
284
283
|
return JSON.parse(await fs.promises.readFile(embeddedFilesLocation, 'utf-8'));
|
|
285
284
|
}
|
|
286
285
|
}
|
|
287
|
-
catch
|
|
286
|
+
catch {
|
|
288
287
|
console.error(`Unable to read 'embeddedFiles.json' from: `, cacheDir);
|
|
289
288
|
}
|
|
290
289
|
return undefined;
|
|
@@ -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 fs from 'fs'\nimport path from 'path'\nimport { cachified, type CacheEntry } from '@epic-web/cachified'\nimport { remember } from '@epic-web/remember'\nimport { remarkCodeBlocksShiki } from '@kentcdodds/md-temp'\nimport fsExtra from 'fs-extra'\nimport { type Element, type Root as HastRoot } from 'hast'\nimport md5 from 'md5-hex'\nimport { type Root as MdastRoot } from 'mdast'\nimport { bundleMDX } from 'mdx-bundler'\nimport PQueue from 'p-queue'\nimport remarkAutolinkHeadings from 'remark-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\ttype CachedEmbeddedFilesList,\n\tcompiledMarkdownCache,\n\tembeddedFilesCache,\n\tshouldForceFresh,\n} from './cache.server.js'\nimport {\n\tremarkCodeFile,\n\ttype CodeFileData,\n\ttype EmbeddedFile,\n} from './codefile-mdx.server.js'\n\nconst cacheDir = path.join(\n\tprocess.env.EPICSHOP_CONTEXT_CWD ?? process.cwd(),\n\t'./node_modules/.cache/compile-mdx',\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\ttrimCodeBlocks,\n\tremarkCodeBlocksShiki,\n\tremovePreContainerDivs,\n] satisfies PluggableList\n\nfunction checkFileExists(file: string) {\n\treturn fs.promises.access(file, fs.constants.F_OK).then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nconst verboseLog =\n\tprocess.env.EPICSHOP_VERBOSE_LOG === 'true' ? console.log : () => {}\n\n/**\n * @param embeddedFiles {string[]} - list of embedded files\n * @param lastCompiledTime {number} - timestamp indicating the last time mdx file was compiled\n * @returns true if all embedded file mtimeMs are older then the file compiled time,\n * false if we need update\n */\nfunction validateEmbeddedFiles(\n\tembeddedFiles: IterableIterator<EmbeddedFile>,\n\tlastCompiledTime: number,\n): Promise<boolean> {\n\tif (process.env.NODE_ENV !== 'development') return Promise.resolve(true)\n\treturn Promise.all(\n\t\tArray.from(embeddedFiles).map(async ({ file }) => {\n\t\t\tconst stat = await fs.promises.stat(file).catch(() => ({ mtimeMs: 0 }))\n\t\t\treturn lastCompiledTime > stat.mtimeMs || Promise.reject()\n\t\t}),\n\t).then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nexport async function compileMdx(\n\tfile: string,\n\t{ request, forceFresh }: { request?: Request; forceFresh?: boolean } = {},\n): Promise<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}> {\n\tif (!(await checkFileExists(file))) {\n\t\tthrow new Error(`File does not exist: ${file}`)\n\t}\n\n\tlet cachedEmbeddedFiles = new Map<string, EmbeddedFile>()\n\n\tconst stat = await fs.promises.stat(file)\n\tconst cacheLocation = path.join(cacheDir, `${md5(file)}.json`)\n\n\tconst requireFresh = await shouldForceFresh({\n\t\tforceFresh,\n\t\trequest,\n\t\tkey: cacheLocation,\n\t})\n\tif (!requireFresh && (await checkFileExists(cacheLocation))) {\n\t\tconst cached = JSON.parse(\n\t\t\tawait fs.promises.readFile(cacheLocation, 'utf-8'),\n\t\t) as any\n\n\t\tcachedEmbeddedFiles = new Map(\n\t\t\tObject.entries(cached.value.embeddedFiles ?? {}),\n\t\t)\n\n\t\tconst compiledTime = cached.value.compiledTime ?? 0\n\t\tconst warningCancled =\n\t\t\tprocess.env.NODE_ENV === 'development'\n\t\t\t\t? cached?.value?.warningCancled ?? false\n\t\t\t\t: false\n\t\tif (\n\t\t\tcompiledTime > stat.mtimeMs &&\n\t\t\t!warningCancled &&\n\t\t\t(await validateEmbeddedFiles(cachedEmbeddedFiles.values(), compiledTime))\n\t\t) {\n\t\t\treturn cached.value\n\t\t}\n\t}\n\tlet title: string | null = null\n\tconst epicVideoEmbeds: Array<string> = []\n\tconst codeFileData = {\n\t\tmdxFile: file,\n\t\tcacheLocation,\n\t\tcachedEmbeddedFiles,\n\t\tembeddedFiles: new Map<string, EmbeddedFile>(),\n\t}\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\tesbuildOptions(options) {\n\t\t\t\toptions.define = {\n\t\t\t\t\t'process.env.NODE_ENV': JSON.stringify(\n\t\t\t\t\t\tprocess.env.NODE_ENV ?? 'production',\n\t\t\t\t\t),\n\t\t\t\t\t...options.define,\n\t\t\t\t}\n\t\t\t\treturn options\n\t\t\t},\n\t\t\tmdxOptions(options) {\n\t\t\t\toptions.remarkPlugins = [\n\t\t\t\t\t...(options.remarkPlugins ?? []),\n\t\t\t\t\t[remarkAutolinkHeadings, { behavior: 'wrap' }],\n\t\t\t\t\tgfm,\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\tvisit(node, 'text', textNode => {\n\t\t\t\t\t\t\t\t\ttitle = textNode.value.trim()\n\t\t\t\t\t\t\t\t})\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\ta => 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\t() => remarkCodeFile(codeFileData),\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\tawait fsExtra.ensureDir(cacheDir)\n\t\tawait fs.promises.writeFile(\n\t\t\tcacheLocation,\n\t\t\tJSON.stringify({\n\t\t\t\tvalue: {\n\t\t\t\t\t...result,\n\t\t\t\t\tcompiledTime: Date.now(),\n\t\t\t\t\tembeddedFiles: codeFileData.embeddedFiles.size\n\t\t\t\t\t\t? Object.fromEntries(codeFileData.embeddedFiles)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t}),\n\t\t)\n\t\tawait updateEmbeddedFilesCache(codeFileData)\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: 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\tesbuildOptions(options) {\n\t\t\t\t\t\toptions.define = {\n\t\t\t\t\t\t\t'process.env.NODE_ENV': JSON.stringify(\n\t\t\t\t\t\t\t\tprocess.env.NODE_ENV ?? 'production',\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t...options.define,\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn options\n\t\t\t\t\t},\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\nconst modifiedEmbeddedFilesTime = remember(\n\t'modified_embedded_files_time',\n\t() => new Map<string, number>(),\n)\n\nconst EMBEDDED_FILES_CACHE_KEY = 'embeddedFilesCache'\n\nasync function updateEmbeddedFilesCache({\n\tmdxFile,\n\tembeddedFiles,\n}: CodeFileData) {\n\tif (mdxFile.includes('playground')) return\n\tlet cachedList = await getEmbeddedFilesCache()\n\tconst hash = cachedList ? md5(JSON.stringify(cachedList)) : null\n\n\t// make sure we get clean list before updating it\n\tif (cachedList) {\n\t\tfor (const [key, value] of Object.entries(cachedList)) {\n\t\t\tcachedList[key] = value.filter(item => item !== mdxFile)\n\t\t\tif (cachedList[key]?.length === 0) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete cachedList[key]\n\t\t\t}\n\t\t}\n\t}\n\n\tif (embeddedFiles.size) {\n\t\tif (!cachedList) {\n\t\t\tcachedList = {}\n\t\t}\n\t\tconst files = Array.from(\n\t\t\tnew Set(Array.from(embeddedFiles.values()).map(({ file }) => file)),\n\t\t).sort()\n\t\tfor (const file of files) {\n\t\t\tcachedList[file] = [...(cachedList[file] ?? []), mdxFile]\n\t\t}\n\t}\n\n\tif (cachedList && hash !== md5(JSON.stringify(cachedList))) {\n\t\tawait fsExtra.ensureDir(cacheDir)\n\t\tconst embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json')\n\t\tmodifiedEmbeddedFilesTime.set(EMBEDDED_FILES_CACHE_KEY, Date.now())\n\t\tawait fs.promises.writeFile(\n\t\t\tembeddedFilesLocation,\n\t\t\tJSON.stringify({ ...cachedList }),\n\t\t)\n\t}\n}\n\nasync function getEmbeddedFilesCache() {\n\tconst key = EMBEDDED_FILES_CACHE_KEY\n\n\tfunction getForceFresh(cacheEntry: CacheEntry | null | undefined) {\n\t\tif (!cacheEntry) return true\n\t\tconst latestModifiedTime = modifiedEmbeddedFilesTime.get(key)\n\t\tif (!latestModifiedTime) return undefined\n\t\treturn latestModifiedTime > cacheEntry.metadata.createdTime\n\t\t\t? true\n\t\t\t: undefined\n\t}\n\n\treturn cachified({\n\t\tkey,\n\t\tcache: embeddedFilesCache,\n\t\tttl: 1000 * 60 * 60 * 24,\n\t\tforceFresh: getForceFresh(embeddedFilesCache.get(key)),\n\t\tgetFreshValue: async () => {\n\t\t\ttry {\n\t\t\t\tconst embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json')\n\t\t\t\tif (await checkFileExists(embeddedFilesLocation)) {\n\t\t\t\t\treturn JSON.parse(\n\t\t\t\t\t\tawait fs.promises.readFile(embeddedFilesLocation, 'utf-8'),\n\t\t\t\t\t) as CachedEmbeddedFilesList\n\t\t\t\t}\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconsole.error(`Unable to read 'embeddedFiles.json' from: `, cacheDir)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t})\n}\n\nexport async function isEmbeddedFile(filePath: string) {\n\tif (process.env.NODE_ENV !== 'development') return false\n\tconst embeddedFilesList = await getEmbeddedFilesCache()\n\tif (embeddedFilesList) {\n\t\tconst embeddedFiles = Object.keys(embeddedFilesList)\n\t\treturn embeddedFiles.includes(filePath.replace(/\\\\/g, '/'))\n\t}\n\treturn false\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\n// TODO: Fix these\n/*\neslint\n\t\"@typescript-eslint/no-unsafe-assignment\": \"off\",\n\t\"@typescript-eslint/no-unsafe-member-access\": \"off\",\n\t\"@typescript-eslint/no-unnecessary-condition\": \"off\",\n\t\"@typescript-eslint/no-unsafe-argument\": \"off\",\n*/\n"]}
|
|
1
|
+
{"version":3,"file":"compile-mdx.server.js","sourceRoot":"","sources":["../../src/compile-mdx.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,SAAS,EAAmB,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,OAAO,MAAM,UAAU,CAAA;AAE9B,OAAO,GAAG,MAAM,SAAS,CAAA;AAEzB,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,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,GAEhB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACN,cAAc,GAGd,MAAM,0BAA0B,CAAA;AAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACzB,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,EAAE,EACjD,mCAAmC,CACnC,CAAA;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;IACd,qBAAqB;IACrB,sBAAsB;CACE,CAAA;AAEzB,SAAS,eAAe,CAAC,IAAY;IACpC,OAAO,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CACtD,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;AACF,CAAC;AAED,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;;;;;GAKG;AACH,SAAS,qBAAqB,CAC7B,aAA6C,EAC7C,gBAAwB;IAExB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACxE,OAAO,OAAO,CAAC,GAAG,CACjB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QAChD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACvE,OAAO,gBAAgB,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAA;IAC3D,CAAC,CAAC,CACF,CAAC,IAAI,CACL,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,IAAY,EACZ,EAAE,OAAO,EAAE,UAAU,KAAkD,EAAE;IAMzE,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,mBAAmB,GAAG,IAAI,GAAG,EAAwB,CAAA;IAEzD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAE9D,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC;QAC3C,UAAU;QACV,OAAO;QACP,GAAG,EAAE,aAAa;KAClB,CAAC,CAAA;IACF,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAC3C,CAAA;QAER,mBAAmB,GAAG,IAAI,GAAG,CAC5B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAChD,CAAA;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;QACnD,MAAM,cAAc,GACnB,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;YACrC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,IAAI,KAAK;YACxC,CAAC,CAAC,KAAK,CAAA;QACT,IACC,YAAY,GAAG,IAAI,CAAC,OAAO;YAC3B,CAAC,cAAc;YACf,CAAC,MAAM,qBAAqB,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,EACxE,CAAC;YACF,OAAO,MAAM,CAAC,KAAK,CAAA;QACpB,CAAC;IACF,CAAC;IACD,IAAI,KAAK,GAAkB,IAAI,CAAA;IAC/B,MAAM,eAAe,GAAkB,EAAE,CAAA;IACzC,MAAM,YAAY,GAAG;QACpB,OAAO,EAAE,IAAI;QACb,aAAa;QACb,mBAAmB;QACnB,aAAa,EAAE,IAAI,GAAG,EAAwB;KAC9C,CAAA;IAED,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,cAAc,CAAC,OAAO;gBACrB,OAAO,CAAC,MAAM,GAAG;oBAChB,sBAAsB,EAAE,IAAI,CAAC,SAAS,CACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,CACpC;oBACD,GAAG,OAAO,CAAC,MAAM;iBACjB,CAAA;gBACD,OAAO,OAAO,CAAA;YACf,CAAC;YACD,UAAU,CAAC,OAAO;gBACjB,OAAO,CAAC,aAAa,GAAG;oBACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;oBAChC,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC9C,GAAG;oBACH,GAAG,EAAE,CAAC,CAAC,IAAe,EAAE,EAAE;wBACzB,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;4BAC7B,IAAI,KAAK;gCAAE,OAAM;4BACjB,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gCACtB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE;oCAC9B,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;gCAC9B,CAAC,CAAC,CAAA;4BACH,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,KAAK,CAAC,EAAE;4BACxC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gCAAE,OAAM;4BACtC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CACrD,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,GAAG,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC;oBAClC,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,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACjC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAC1B,aAAa,EACb,IAAI,CAAC,SAAS,CAAC;YACd,KAAK,EAAE;gBACN,GAAG,MAAM;gBACT,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;gBACxB,aAAa,EAAE,YAAY,CAAC,aAAa,CAAC,IAAI;oBAC7C,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,aAAa,CAAC;oBAChD,CAAC,CAAC,SAAS;aACZ;SACD,CAAC,CACF,CAAA;QACD,MAAM,wBAAwB,CAAC,YAAY,CAAC,CAAA;QAC5C,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,cAAc;QACnB,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,cAAc,CAAC,OAAO;wBACrB,OAAO,CAAC,MAAM,GAAG;4BAChB,sBAAsB,EAAE,IAAI,CAAC,SAAS,CACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,CACpC;4BACD,GAAG,OAAO,CAAC,MAAM;yBACjB,CAAA;wBACD,OAAO,OAAO,CAAA;oBACf,CAAC;oBACD,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,MAAM,yBAAyB,GAAG,QAAQ,CACzC,8BAA8B,EAC9B,GAAG,EAAE,CAAC,IAAI,GAAG,EAAkB,CAC/B,CAAA;AAED,MAAM,wBAAwB,GAAG,oBAAoB,CAAA;AAErD,KAAK,UAAU,wBAAwB,CAAC,EACvC,OAAO,EACP,aAAa,GACC;IACd,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAM;IAC1C,IAAI,UAAU,GAAG,MAAM,qBAAqB,EAAE,CAAA;IAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAEhE,iDAAiD;IACjD,IAAI,UAAU,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACvD,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAA;YACxD,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAA;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,UAAU,GAAG,EAAE,CAAA;QAChB,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CACnE,CAAC,IAAI,EAAE,CAAA;QACR,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;QAC1D,CAAC;IACF,CAAC;IAED,IAAI,UAAU,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACjC,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAA;QACvE,yBAAyB,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QACnE,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAC1B,qBAAqB,EACrB,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CACjC,CAAA;IACF,CAAC;AACF,CAAC;AAED,KAAK,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,wBAAwB,CAAA;IAEpC,SAAS,aAAa,CAAC,UAAyC;QAC/D,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAA;QAC5B,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC7D,IAAI,CAAC,kBAAkB;YAAE,OAAO,SAAS,CAAA;QACzC,OAAO,kBAAkB,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW;YAC1D,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,SAAS,CAAA;IACb,CAAC;IAED,OAAO,SAAS,CAAC;QAChB,GAAG;QACH,KAAK,EAAE,kBAAkB;QACzB,GAAG,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACxB,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtD,aAAa,EAAE,KAAK,IAAI,EAAE;YACzB,IAAI,CAAC;gBACJ,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAA;gBACvE,IAAI,MAAM,eAAe,CAAC,qBAAqB,CAAC,EAAE,CAAC;oBAClD,OAAO,IAAI,CAAC,KAAK,CAChB,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAC/B,CAAA;gBAC7B,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;gBACR,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,QAAQ,CAAC,CAAA;YACtE,CAAC;YACD,OAAO,SAAS,CAAA;QACjB,CAAC;KACD,CAAC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,KAAK,CAAA;IACxD,MAAM,iBAAiB,GAAG,MAAM,qBAAqB,EAAE,CAAA;IACvD,IAAI,iBAAiB,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACpD,OAAO,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,KAAK,CAAA;AACb,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,cAAc,EAAE,IAAI;QACpB,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;AAED,kBAAkB;AAClB;;;;;;EAME","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { cachified, type CacheEntry } from '@epic-web/cachified'\nimport { remember } from '@epic-web/remember'\nimport { remarkCodeBlocksShiki } from '@kentcdodds/md-temp'\nimport fsExtra from 'fs-extra'\nimport { type Element, type Root as HastRoot } from 'hast'\nimport md5 from 'md5-hex'\nimport { type Root as MdastRoot } from 'mdast'\nimport { bundleMDX } from 'mdx-bundler'\nimport PQueue from 'p-queue'\nimport remarkAutolinkHeadings from 'remark-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\tcompiledMarkdownCache,\n\tembeddedFilesCache,\n\tshouldForceFresh,\n\ttype CachedEmbeddedFilesList,\n} from './cache.server.js'\nimport {\n\tremarkCodeFile,\n\ttype CodeFileData,\n\ttype EmbeddedFile,\n} from './codefile-mdx.server.js'\n\nconst cacheDir = path.join(\n\tprocess.env.EPICSHOP_CONTEXT_CWD ?? process.cwd(),\n\t'./node_modules/.cache/compile-mdx',\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\ttrimCodeBlocks,\n\tremarkCodeBlocksShiki,\n\tremovePreContainerDivs,\n] satisfies PluggableList\n\nfunction checkFileExists(file: string) {\n\treturn fs.promises.access(file, fs.constants.F_OK).then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nconst verboseLog =\n\tprocess.env.EPICSHOP_VERBOSE_LOG === 'true' ? console.log : () => {}\n\n/**\n * @param embeddedFiles {string[]} - list of embedded files\n * @param lastCompiledTime {number} - timestamp indicating the last time mdx file was compiled\n * @returns true if all embedded file mtimeMs are older then the file compiled time,\n * false if we need update\n */\nfunction validateEmbeddedFiles(\n\tembeddedFiles: IterableIterator<EmbeddedFile>,\n\tlastCompiledTime: number,\n): Promise<boolean> {\n\tif (process.env.NODE_ENV !== 'development') return Promise.resolve(true)\n\treturn Promise.all(\n\t\tArray.from(embeddedFiles).map(async ({ file }) => {\n\t\t\tconst stat = await fs.promises.stat(file).catch(() => ({ mtimeMs: 0 }))\n\t\t\treturn lastCompiledTime > stat.mtimeMs || Promise.reject()\n\t\t}),\n\t).then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nexport async function compileMdx(\n\tfile: string,\n\t{ request, forceFresh }: { request?: Request; forceFresh?: boolean } = {},\n): Promise<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}> {\n\tif (!(await checkFileExists(file))) {\n\t\tthrow new Error(`File does not exist: ${file}`)\n\t}\n\n\tlet cachedEmbeddedFiles = new Map<string, EmbeddedFile>()\n\n\tconst stat = await fs.promises.stat(file)\n\tconst cacheLocation = path.join(cacheDir, `${md5(file)}.json`)\n\n\tconst requireFresh = await shouldForceFresh({\n\t\tforceFresh,\n\t\trequest,\n\t\tkey: cacheLocation,\n\t})\n\tif (!requireFresh && (await checkFileExists(cacheLocation))) {\n\t\tconst cached = JSON.parse(\n\t\t\tawait fs.promises.readFile(cacheLocation, 'utf-8'),\n\t\t) as any\n\n\t\tcachedEmbeddedFiles = new Map(\n\t\t\tObject.entries(cached.value.embeddedFiles ?? {}),\n\t\t)\n\n\t\tconst compiledTime = cached.value.compiledTime ?? 0\n\t\tconst warningCancled =\n\t\t\tprocess.env.NODE_ENV === 'development'\n\t\t\t\t? cached?.value?.warningCancled ?? false\n\t\t\t\t: false\n\t\tif (\n\t\t\tcompiledTime > stat.mtimeMs &&\n\t\t\t!warningCancled &&\n\t\t\t(await validateEmbeddedFiles(cachedEmbeddedFiles.values(), compiledTime))\n\t\t) {\n\t\t\treturn cached.value\n\t\t}\n\t}\n\tlet title: string | null = null\n\tconst epicVideoEmbeds: Array<string> = []\n\tconst codeFileData = {\n\t\tmdxFile: file,\n\t\tcacheLocation,\n\t\tcachedEmbeddedFiles,\n\t\tembeddedFiles: new Map<string, EmbeddedFile>(),\n\t}\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\tesbuildOptions(options) {\n\t\t\t\toptions.define = {\n\t\t\t\t\t'process.env.NODE_ENV': JSON.stringify(\n\t\t\t\t\t\tprocess.env.NODE_ENV ?? 'production',\n\t\t\t\t\t),\n\t\t\t\t\t...options.define,\n\t\t\t\t}\n\t\t\t\treturn options\n\t\t\t},\n\t\t\tmdxOptions(options) {\n\t\t\t\toptions.remarkPlugins = [\n\t\t\t\t\t...(options.remarkPlugins ?? []),\n\t\t\t\t\t[remarkAutolinkHeadings, { behavior: 'wrap' }],\n\t\t\t\t\tgfm,\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\tvisit(node, 'text', textNode => {\n\t\t\t\t\t\t\t\t\ttitle = textNode.value.trim()\n\t\t\t\t\t\t\t\t})\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\ta => 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\t() => remarkCodeFile(codeFileData),\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\tawait fsExtra.ensureDir(cacheDir)\n\t\tawait fs.promises.writeFile(\n\t\t\tcacheLocation,\n\t\t\tJSON.stringify({\n\t\t\t\tvalue: {\n\t\t\t\t\t...result,\n\t\t\t\t\tcompiledTime: Date.now(),\n\t\t\t\t\tembeddedFiles: codeFileData.embeddedFiles.size\n\t\t\t\t\t\t? Object.fromEntries(codeFileData.embeddedFiles)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t}),\n\t\t)\n\t\tawait updateEmbeddedFilesCache(codeFileData)\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: 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\tesbuildOptions(options) {\n\t\t\t\t\t\toptions.define = {\n\t\t\t\t\t\t\t'process.env.NODE_ENV': JSON.stringify(\n\t\t\t\t\t\t\t\tprocess.env.NODE_ENV ?? 'production',\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t...options.define,\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn options\n\t\t\t\t\t},\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\nconst modifiedEmbeddedFilesTime = remember(\n\t'modified_embedded_files_time',\n\t() => new Map<string, number>(),\n)\n\nconst EMBEDDED_FILES_CACHE_KEY = 'embeddedFilesCache'\n\nasync function updateEmbeddedFilesCache({\n\tmdxFile,\n\tembeddedFiles,\n}: CodeFileData) {\n\tif (mdxFile.includes('playground')) return\n\tlet cachedList = await getEmbeddedFilesCache()\n\tconst hash = cachedList ? md5(JSON.stringify(cachedList)) : null\n\n\t// make sure we get clean list before updating it\n\tif (cachedList) {\n\t\tfor (const [key, value] of Object.entries(cachedList)) {\n\t\t\tcachedList[key] = value.filter(item => item !== mdxFile)\n\t\t\tif (cachedList[key]?.length === 0) {\n\t\t\t\tdelete cachedList[key]\n\t\t\t}\n\t\t}\n\t}\n\n\tif (embeddedFiles.size) {\n\t\tif (!cachedList) {\n\t\t\tcachedList = {}\n\t\t}\n\t\tconst files = Array.from(\n\t\t\tnew Set(Array.from(embeddedFiles.values()).map(({ file }) => file)),\n\t\t).sort()\n\t\tfor (const file of files) {\n\t\t\tcachedList[file] = [...(cachedList[file] ?? []), mdxFile]\n\t\t}\n\t}\n\n\tif (cachedList && hash !== md5(JSON.stringify(cachedList))) {\n\t\tawait fsExtra.ensureDir(cacheDir)\n\t\tconst embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json')\n\t\tmodifiedEmbeddedFilesTime.set(EMBEDDED_FILES_CACHE_KEY, Date.now())\n\t\tawait fs.promises.writeFile(\n\t\t\tembeddedFilesLocation,\n\t\t\tJSON.stringify({ ...cachedList }),\n\t\t)\n\t}\n}\n\nasync function getEmbeddedFilesCache() {\n\tconst key = EMBEDDED_FILES_CACHE_KEY\n\n\tfunction getForceFresh(cacheEntry: CacheEntry | null | undefined) {\n\t\tif (!cacheEntry) return true\n\t\tconst latestModifiedTime = modifiedEmbeddedFilesTime.get(key)\n\t\tif (!latestModifiedTime) return undefined\n\t\treturn latestModifiedTime > cacheEntry.metadata.createdTime\n\t\t\t? true\n\t\t\t: undefined\n\t}\n\n\treturn cachified({\n\t\tkey,\n\t\tcache: embeddedFilesCache,\n\t\tttl: 1000 * 60 * 60 * 24,\n\t\tforceFresh: getForceFresh(embeddedFilesCache.get(key)),\n\t\tgetFreshValue: async () => {\n\t\t\ttry {\n\t\t\t\tconst embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json')\n\t\t\t\tif (await checkFileExists(embeddedFilesLocation)) {\n\t\t\t\t\treturn JSON.parse(\n\t\t\t\t\t\tawait fs.promises.readFile(embeddedFilesLocation, 'utf-8'),\n\t\t\t\t\t) as CachedEmbeddedFilesList\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsole.error(`Unable to read 'embeddedFiles.json' from: `, cacheDir)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t})\n}\n\nexport async function isEmbeddedFile(filePath: string) {\n\tif (process.env.NODE_ENV !== 'development') return false\n\tconst embeddedFilesList = await getEmbeddedFilesCache()\n\tif (embeddedFilesList) {\n\t\tconst embeddedFiles = Object.keys(embeddedFilesList)\n\t\treturn embeddedFiles.includes(filePath.replace(/\\\\/g, '/'))\n\t}\n\treturn false\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\n// TODO: Fix these\n/*\neslint\n\t\"@typescript-eslint/no-unsafe-assignment\": \"off\",\n\t\"@typescript-eslint/no-unsafe-member-access\": \"off\",\n\t\"@typescript-eslint/no-unnecessary-condition\": \"off\",\n\t\"@typescript-eslint/no-unsafe-argument\": \"off\",\n*/\n"]}
|
package/dist/esm/db.server.d.ts
CHANGED
|
@@ -56,13 +56,13 @@ export declare const PlayerPreferencesSchema: z.ZodDefault<z.ZodOptional<z.ZodOb
|
|
|
56
56
|
defaultView?: string | undefined;
|
|
57
57
|
activeSidebarTab?: number | undefined;
|
|
58
58
|
}, {
|
|
59
|
-
volumeRate?: number | undefined;
|
|
60
|
-
playbackRate?: number | undefined;
|
|
61
|
-
autoplay?: boolean | undefined;
|
|
62
59
|
subtitle?: {
|
|
63
60
|
id?: string | null | undefined;
|
|
64
61
|
mode?: "disabled" | "hidden" | "showing" | null | undefined;
|
|
65
62
|
} | undefined;
|
|
63
|
+
volumeRate?: number | undefined;
|
|
64
|
+
playbackRate?: number | undefined;
|
|
65
|
+
autoplay?: boolean | undefined;
|
|
66
66
|
muted?: boolean | undefined;
|
|
67
67
|
theater?: boolean | undefined;
|
|
68
68
|
defaultView?: string | undefined;
|
|
@@ -138,13 +138,13 @@ export declare function getPreferences(): Promise<{
|
|
|
138
138
|
};
|
|
139
139
|
} | null>;
|
|
140
140
|
export declare function setPlayerPreferences(playerPreferences: z.input<typeof PlayerPreferencesSchema>): Promise<{
|
|
141
|
-
volumeRate?: number | undefined;
|
|
142
|
-
playbackRate?: number | undefined;
|
|
143
|
-
autoplay?: boolean | undefined;
|
|
144
141
|
subtitle?: {
|
|
145
142
|
id?: string | null | undefined;
|
|
146
143
|
mode?: "disabled" | "hidden" | "showing" | null | undefined;
|
|
147
144
|
} | undefined;
|
|
145
|
+
volumeRate?: number | undefined;
|
|
146
|
+
playbackRate?: number | undefined;
|
|
147
|
+
autoplay?: boolean | undefined;
|
|
148
148
|
muted?: boolean | undefined;
|
|
149
149
|
theater?: boolean | undefined;
|
|
150
150
|
defaultView?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iframe-sync.d.ts","sourceRoot":"","sources":["../../src/iframe-sync.tsx"],"names":[],"mappings":"AAwBA,KAAK,eAAe,GAAG;IACtB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IACpE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAA;CACzE,CAAA;AAgCD,wBAAgB,kBAAkB,CAAC,SAAS,SAAS,eAAe,EAAE,EACrE,KAAK,EACL,QAAQ,GACR,EAAE;IACF,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;CACvC,
|
|
1
|
+
{"version":3,"file":"iframe-sync.d.ts","sourceRoot":"","sources":["../../src/iframe-sync.tsx"],"names":[],"mappings":"AAwBA,KAAK,eAAe,GAAG;IACtB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IACpE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAA;CACzE,CAAA;AAgCD,wBAAgB,kBAAkB,CAAC,SAAS,SAAS,eAAe,EAAE,EACrE,KAAK,EACL,QAAQ,GACR,EAAE;IACF,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;CACvC,OAiDA"}
|
package/dist/esm/iframe-sync.js
CHANGED
|
@@ -59,7 +59,6 @@ export function EpicShopIFrameSync({ React, navigate, }) {
|
|
|
59
59
|
if (window.parent === window)
|
|
60
60
|
return;
|
|
61
61
|
// @ts-expect-error - this is fine 🔥
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
63
62
|
window.__epicshop__?.onHydrated?.();
|
|
64
63
|
const methods = [
|
|
65
64
|
'pushState',
|
|
@@ -71,7 +70,6 @@ export function EpicShopIFrameSync({ React, navigate, }) {
|
|
|
71
70
|
for (const method of methods) {
|
|
72
71
|
// @ts-expect-error - this is fine 🔥
|
|
73
72
|
window.history[method] = new Proxy(window.history[method], {
|
|
74
|
-
// eslint-disable-next-line no-loop-func
|
|
75
73
|
apply(target, thisArg, argArray) {
|
|
76
74
|
window.parent.postMessage({ type: 'epicshop:history-call', method, args: argArray }, '*');
|
|
77
75
|
// @ts-expect-error - this is fine too 🙃
|
|
@@ -83,10 +81,8 @@ export function EpicShopIFrameSync({ React, navigate, }) {
|
|
|
83
81
|
// listen for messages from parent
|
|
84
82
|
React.useEffect(() => {
|
|
85
83
|
function handleMessage(event) {
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
87
84
|
const { type, params } = event.data;
|
|
88
85
|
if (type === 'epicshop:navigate-call') {
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
90
86
|
navigate(...params);
|
|
91
87
|
}
|
|
92
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iframe-sync.js","sourceRoot":"","sources":["../../src/iframe-sync.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,IAAI,WAAW,GAAG,KAAK,CAAA;AAOvB,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BzC,CAAA;AAED,MAAM,UAAU,kBAAkB,CAAoC,EACrE,KAAK,EACL,QAAQ,GAIR;IACA,0BAA0B;IAC1B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,WAAW;YAAE,OAAM;QACvB,WAAW,GAAG,IAAI,CAAA;QAClB,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;YAAE,OAAM;QAEpC,qCAAqC;
|
|
1
|
+
{"version":3,"file":"iframe-sync.js","sourceRoot":"","sources":["../../src/iframe-sync.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,IAAI,WAAW,GAAG,KAAK,CAAA;AAOvB,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BzC,CAAA;AAED,MAAM,UAAU,kBAAkB,CAAoC,EACrE,KAAK,EACL,QAAQ,GAIR;IACA,0BAA0B;IAC1B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,WAAW;YAAE,OAAM;QACvB,WAAW,GAAG,IAAI,CAAA;QAClB,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;YAAE,OAAM;QAEpC,qCAAqC;QAErC,MAAM,CAAC,YAAY,EAAE,UAAU,EAAE,EAAE,CAAA;QAEnC,MAAM,OAAO,GAAG;YACf,WAAW;YACX,cAAc;YACd,IAAI;YACJ,SAAS;YACT,MAAM;SACG,CAAA;QACV,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,qCAAqC;YACrC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;gBAC1D,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ;oBAC9B,MAAM,CAAC,MAAM,CAAC,WAAW,CACxB,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EACzD,GAAG,CACH,CAAA;oBACD,yCAAyC;oBACzC,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;gBACvC,CAAC;aACD,CAAC,CAAA;QACH,CAAC;IACF,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,kCAAkC;IAClC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,SAAS,aAAa,CAAC,KAAmB;YACzC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAA;YACnC,IAAI,IAAI,KAAK,wBAAwB,EAAE,CAAC;gBACvC,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAA;YACpB,CAAC;QACF,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACjD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAClE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,OAAO,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE;QACpC,IAAI,EAAE,QAAQ;QACd,uBAAuB,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE;KACrD,CAAC,CAAA;AACH,CAAC","sourcesContent":["/*\nThis file is kinda weird. EpicShop actually bundles react and react router to\navoid getting version clashes, but this component is used in the \"host\"\napplication. Anything we use in this file will be this file's version of that\ndependency, which in the case of bundled dependencies would be different from\nthe host app's version. We want to avoid shipping two versions of React and\nreact-router to the client. So we need to accept React and navigate as props\nrather than just using those things directly.\n\nTo reduce the annoyance, we'll have the host applications have a file like this:\n\n// Ignore this file please\nimport { EpicShopIFrameSync } from '@epic-web/workshop-utils/iframe-sync'\nimport { useNavigate } from '@remix-run/react'\nimport * as React from 'react'\n\nexport function EpicShop() {\n\tconst navigate = useNavigate()\n\treturn <EpicShopIFrameSync React={React} navigate={navigate} />\n}\n\n */\nlet effectSetup = false\n\ntype CustomReactType = {\n\tuseEffect: (cb: () => (() => void) | void, deps: Array<any>) => void\n\tcreateElement: (type: string, props: any, ...children: Array<any>) => any\n}\n\nconst iframeSyncScript = /* javascript */ `\nif (window.parent !== window) {\n\twindow.__epicshop__ = window.__epicshop__ || {};\n\twindow.parent.postMessage(\n\t\t{ type: 'epicshop:loaded', url: window.location.href },\n\t\t'*'\n\t);\n\tfunction handleMessage(event) {\n\t\tconst { type, params } = event.data\n\t\tif (type === 'epicshop:navigate-call') {\n\t\t\tconst [distanceOrUrl, options] = params\n\t\t\tif (typeof distanceOrUrl === 'number') {\n\t\t\t\twindow.history.go(distanceOrUrl)\n\t\t\t} else {\n\t\t\t\tif (options?.replace) {\n\t\t\t\t\twindow.location.replace(distanceOrUrl)\n\t\t\t\t} else {\n\t\t\t\t\twindow.location.assign(distanceOrUrl)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\twindow.addEventListener('message', handleMessage)\n\twindow.__epicshop__.onHydrated = function() {\n\t\twindow.removeEventListener('message', handleMessage)\n\t};\n}\n`\n\nexport function EpicShopIFrameSync<ReactType extends CustomReactType>({\n\tReact,\n\tnavigate,\n}: {\n\tReact: ReactType\n\tnavigate: (...args: Array<any>) => void\n}) {\n\t// communicate with parent\n\tReact.useEffect(() => {\n\t\tif (effectSetup) return\n\t\teffectSetup = true\n\t\tif (window.parent === window) return\n\n\t\t// @ts-expect-error - this is fine 🔥\n\n\t\twindow.__epicshop__?.onHydrated?.()\n\n\t\tconst methods = [\n\t\t\t'pushState',\n\t\t\t'replaceState',\n\t\t\t'go',\n\t\t\t'forward',\n\t\t\t'back',\n\t\t] as const\n\t\tfor (const method of methods) {\n\t\t\t// @ts-expect-error - this is fine 🔥\n\t\t\twindow.history[method] = new Proxy(window.history[method], {\n\t\t\t\tapply(target, thisArg, argArray) {\n\t\t\t\t\twindow.parent.postMessage(\n\t\t\t\t\t\t{ type: 'epicshop:history-call', method, args: argArray },\n\t\t\t\t\t\t'*',\n\t\t\t\t\t)\n\t\t\t\t\t// @ts-expect-error - this is fine too 🙃\n\t\t\t\t\treturn target.apply(thisArg, argArray)\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}, [])\n\n\t// listen for messages from parent\n\tReact.useEffect(() => {\n\t\tfunction handleMessage(event: MessageEvent) {\n\t\t\tconst { type, params } = event.data\n\t\t\tif (type === 'epicshop:navigate-call') {\n\t\t\t\tnavigate(...params)\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener('message', handleMessage)\n\t\treturn () => window.removeEventListener('message', handleMessage)\n\t}, [navigate])\n\n\treturn React.createElement('script', {\n\t\ttype: 'module',\n\t\tdangerouslySetInnerHTML: { __html: iframeSyncScript },\n\t})\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright.server.d.ts","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"AAKA,wBAAsB,qBAAqB;;;KAe1C;AAuBD,wBAAgB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"playwright.server.d.ts","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"AAKA,wBAAsB,qBAAqB;;;KAe1C;AAuBD,wBAAgB,mBAAmB,SA2DlC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { expect, test } from '@playwright/test';
|
|
2
2
|
import crossSpawn from 'cross-spawn';
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
import { getApps, isProblemApp } from './apps.server.js';
|
|
@@ -50,7 +50,6 @@ export function setupInBrowserTests() {
|
|
|
50
50
|
.array(z.object({ path: z.string() }))
|
|
51
51
|
.parse(JSON.parse(result.stdout));
|
|
52
52
|
for (const testPage of testPages) {
|
|
53
|
-
// eslint-disable-next-line no-loop-func
|
|
54
53
|
test(testPage.path, async ({ page }) => {
|
|
55
54
|
const errors = [];
|
|
56
55
|
const logs = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright.server.js","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"playwright.server.js","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, test } from '@playwright/test'\nimport crossSpawn from 'cross-spawn'\nimport z from 'zod'\nimport { getApps, isProblemApp } from './apps.server.js'\n\nexport async function getInBrowserTestPages() {\n\tconst apps = (await getApps())\n\t\t.filter(isProblemApp)\n\t\t.filter(a => a.test.type === 'browser')\n\tconst pages = apps.map(app => {\n\t\tif (app.test.type !== 'browser') return null\n\t\tconst { pathname } = app.test\n\t\treturn app.test.testFiles.map(testFile => {\n\t\t\treturn {\n\t\t\t\tpath: `${pathname}${testFile}`,\n\t\t\t\ttestFile,\n\t\t\t}\n\t\t})\n\t})\n\treturn pages.filter(Boolean).flat()\n}\n\nconst sleep = (time: number) =>\n\tnew Promise(resolve => setTimeout(resolve, time))\n\nasync function waitFor<ReturnValue>(\n\tcb: () => ReturnValue | Promise<ReturnValue> | undefined | null,\n\t{ timeout = 1000, interval = 30 } = {},\n) {\n\tconst timeEnd = Date.now() + timeout\n\tlet lastError: unknown | null = null\n\twhile (Date.now() < timeEnd) {\n\t\ttry {\n\t\t\tconst result = await cb()\n\t\t\tif (result) return result\n\t\t} catch (error) {\n\t\t\tlastError = error\n\t\t}\n\t\tawait sleep(interval)\n\t}\n\tthrow lastError || new Error(`waitFor timed out after ${timeout}ms`)\n}\n\nexport function setupInBrowserTests() {\n\t// doing this because playwright needs the tests to be registered synchoronously\n\tconst code = `import('@epic-web/workshop-utils/playwright.server').then(({ getInBrowserTestPages }) => getInBrowserTestPages().then(r => console.log(JSON.stringify(r))))`\n\tconst result = crossSpawn.sync('node', ['--eval', code], {\n\t\tencoding: 'utf-8',\n\t})\n\tif (result.status !== 0) {\n\t\tconsole.error(result.output.join('\\n'))\n\t\tthrow new Error(\n\t\t\t`Failed to get in-browser test pages. Status: ${result.status}.`,\n\t\t)\n\t}\n\tconst testPages = z\n\t\t.array(z.object({ path: z.string() }))\n\t\t.parse(JSON.parse(result.stdout))\n\n\tfor (const testPage of testPages) {\n\t\ttest(testPage.path, async ({ page }) => {\n\t\t\tconst errors: Array<string> = []\n\t\t\tconst logs: Array<string> = []\n\t\t\tconst infos: Array<string> = []\n\t\t\tpage.on('console', message => {\n\t\t\t\tswitch (message.type()) {\n\t\t\t\t\tcase 'error': {\n\t\t\t\t\t\terrors.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'log': {\n\t\t\t\t\t\tlogs.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'info': {\n\t\t\t\t\t\tinfos.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait page.goto(testPage.path)\n\t\t\tawait page.waitForLoadState()\n\t\t\tawait waitFor(\n\t\t\t\t() => infos.find(info => info.includes('status: pending')),\n\t\t\t\t{ timeout: 10_000 },\n\t\t\t)\n\t\t\tconst result = await Promise.race([\n\t\t\t\twaitFor(() => logs.find(log => log.includes('status: pass')), {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t}),\n\t\t\t\twaitFor(() => (errors.length > 0 ? errors : null), {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t}).then(errors => {\n\t\t\t\t\tthrow errors\n\t\t\t\t}),\n\t\t\t])\n\t\t\texpect(result).toContain('status: pass')\n\t\t})\n\t}\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import { type ChildProcess } from 'child_process';
|
|
3
3
|
import closeWithGrace from 'close-with-grace';
|
|
4
|
+
import { type ResultPromise } from 'execa';
|
|
4
5
|
import { type App } from './apps.server.js';
|
|
5
6
|
type DevProcessesMap = Map<string, {
|
|
6
7
|
color: (typeof colors)[number];
|
|
@@ -13,7 +14,7 @@ type OutputLine = {
|
|
|
13
14
|
timestamp: number;
|
|
14
15
|
};
|
|
15
16
|
type TestProcessEntry = {
|
|
16
|
-
process:
|
|
17
|
+
process: ResultPromise | null;
|
|
17
18
|
output: Array<OutputLine>;
|
|
18
19
|
exitCode?: number | null;
|
|
19
20
|
};
|
|
@@ -43,7 +44,18 @@ export declare function runAppDev(app: App): Promise<{
|
|
|
43
44
|
readonly error?: undefined;
|
|
44
45
|
readonly portNumber?: undefined;
|
|
45
46
|
}>;
|
|
46
|
-
export declare function runAppTests(app: App): Promise<import("execa").
|
|
47
|
+
export declare function runAppTests(app: App): Promise<import("execa").Result<{
|
|
48
|
+
cwd: string;
|
|
49
|
+
shell: true;
|
|
50
|
+
stdio: ["ignore", "pipe", "pipe"];
|
|
51
|
+
env: {
|
|
52
|
+
NODE_ENV: "development";
|
|
53
|
+
PORT: string | undefined;
|
|
54
|
+
APP_SERVER_PORT: string | undefined;
|
|
55
|
+
REMIX_DEV_SERVER_WS_PORT: string;
|
|
56
|
+
TZ?: string | undefined;
|
|
57
|
+
};
|
|
58
|
+
}> | {
|
|
47
59
|
readonly status: "error";
|
|
48
60
|
readonly error: "no-test";
|
|
49
61
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.server.d.ts","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"process-manager.server.d.ts","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":";AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAIxD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAO3C,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,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,aAAa,GAAG,IAAI,CAAA;IAC7B,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,CAAA;CAC5E;AAmCD,QAAA,MAAM,MAAM,mIAWF,CAAA;AAEV,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;GAoEvC;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;GAmDzC;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;UAuBvC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WASjD;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,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,iBAoB7C;AAID,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAInD;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAWnE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.server.js","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn } 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 { execaCommand } from 'execa'\nimport fkill from 'fkill'\nimport { type App } from './apps.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 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}\n\nconst devProcesses = remember('dev_processes', getDevProcessesMap)\nconst testProcesses = remember('test_processes', getTestProcessesMap)\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\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\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 availableColors = colors.filter(color =>\n\t\tArray.from(devProcesses.values()).every(p => p.color !== color),\n\t)\n\tconst color =\n\t\tavailableColors[devProcesses.size % availableColors.length] ?? 'blue'\n\tconst appProcess = spawn('npm', ['run', 'dev'], {\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 = execaCommand(app.test.script, {\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\tvoid testProcess.on('exit', code => {\n\t\ttestProcess.stdout?.off('data', handleStdOutData)\n\t\ttestProcess.stderr?.off('data', handleStdErrData)\n\t\t// don't delete the entry from the map so we can show the output at any time\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\tawait fetch(`http://localhost:${app.dev.portNumber}`, {\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 function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess) return false\n\t\tdevProcess.process.kill(0)\n\t\treturn true\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 }\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\tawait execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/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 { 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 { execaCommand, type ResultPromise } from 'execa'\nimport fkill from 'fkill'\nimport { type App } from './apps.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 OutputLine = {\n\ttype: 'stdout' | 'stderr'\n\tcontent: string\n\ttimestamp: number\n}\n\ntype TestProcessEntry = {\n\tprocess: ResultPromise | 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}\n\nconst devProcesses = remember('dev_processes', getDevProcessesMap)\nconst testProcesses = remember('test_processes', getTestProcessesMap)\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\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\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 availableColors = colors.filter(color =>\n\t\tArray.from(devProcesses.values()).every(p => p.color !== color),\n\t)\n\tconst color =\n\t\tavailableColors[devProcesses.size % availableColors.length] ?? 'blue'\n\tconst appProcess = spawn('npm', ['run', 'dev'], {\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 = execaCommand(app.test.script, {\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\tvoid testProcess.on('exit', code => {\n\t\ttestProcess.stdout?.off('data', handleStdOutData)\n\t\ttestProcess.stderr?.off('data', handleStdErrData)\n\t\t// don't delete the entry from the map so we can show the output at any time\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\tawait fetch(`http://localhost:${app.dev.portNumber}`, {\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 function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess) return false\n\t\tdevProcess.process.kill(0)\n\t\treturn true\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 }\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\tawait execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/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"]}
|
package/dist/esm/test.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":";AAWA,eAAO,MAAQ,MAAM,mBAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":";AAWA,eAAO,MAAQ,MAAM,mBAAS,CAAA;AAW9B,wBAAsB,QAAQ,CAAC,WAAW,EACzC,KAAK,EACF,MAAM,GACN,CAAC,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC,EAC1E,GAAG,EAAE,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GACrD,OAAO,CAAC,WAAW,CAAC,CA+BtB"}
|
package/dist/esm/test.js
CHANGED
|
@@ -11,7 +11,6 @@ function isError(maybeError) {
|
|
|
11
11
|
return (maybeError &&
|
|
12
12
|
typeof maybeError === 'object' &&
|
|
13
13
|
'message' in maybeError &&
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
15
14
|
typeof maybeError.message === 'string');
|
|
16
15
|
}
|
|
17
16
|
export async function testStep(title, get) {
|
package/dist/esm/test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,OAAO,MAAM,UAAU,CAAA;AAE9B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEjB,0DAA0D;AAC1D,SAAS,CAAC;IACT,eAAe,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,eAAe,CAAC;CACjE,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;AAE9B,SAAS,OAAO,CAAC,UAAe;IAC/B,OAAO,CACN,UAAU;QACV,OAAO,UAAU,KAAK,QAAQ;QAC9B,SAAS,IAAI,UAAU;QACvB,
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,OAAO,MAAM,UAAU,CAAA;AAE9B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEjB,0DAA0D;AAC1D,SAAS,CAAC;IACT,eAAe,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,eAAe,CAAC;CACjE,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;AAE9B,SAAS,OAAO,CAAC,UAAe;IAC/B,OAAO,CACN,UAAU;QACV,OAAO,UAAU,KAAK,QAAQ;QAC9B,SAAS,IAAI,UAAU;QACvB,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,CACtC,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAE0E,EAC1E,GAAuD;IAEvD,IAAI,WAAW,CAAA;IACf,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAA;QAC1B,MAAM,WAAW,GAChB,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE,CAAC,CAAA;QAChC,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,MAAM,CAAC,WAAW,CACxB;gBACC,IAAI,EAAE,2BAA2B;gBACjC,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,EACD,GAAG,CACH,CAAA;QACF,CAAC;QACD,OAAO,MAAM,CAAA;IACd,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACrB,WAAW,GAAG,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC;QACjC,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;IAC7E,MAAM,WAAW,GAChB,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACrE,KAAK,CAAC,OAAO,GAAG,GAAG,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IAC9E,MAAM,KAAK,CAAA;AACZ,CAAC","sourcesContent":["import { configure } from '@testing-library/dom'\nimport * as chai from 'chai'\nimport chaiDOM from 'chai-dom'\n\nchai.use(chaiDOM)\n\n// in the browser logging out the element is not necessary\nconfigure({\n\tgetElementError: message => new Error(message ?? 'Unknown error'),\n})\n\nexport const { expect } = chai\n\nfunction isError(maybeError: any): maybeError is Error {\n\treturn (\n\t\tmaybeError &&\n\t\ttypeof maybeError === 'object' &&\n\t\t'message' in maybeError &&\n\t\ttypeof maybeError.message === 'string'\n\t)\n}\n\nexport async function testStep<ReturnValue>(\n\ttitle:\n\t\t| string\n\t\t| ((result: { type: 'fail'; error: Error } | { type: 'pass' }) => string),\n\tget: (() => ReturnValue) | (() => Promise<ReturnValue>),\n): Promise<ReturnValue> {\n\tlet caughtError\n\ttry {\n\t\tconst result = await get()\n\t\tconst titleString =\n\t\t\ttypeof title === 'function' ? title({ type: 'pass' }) : title\n\t\tif (window.parent === window) {\n\t\t\tconsole.log(`✅ ${titleString}`)\n\t\t} else {\n\t\t\twindow.parent.postMessage(\n\t\t\t\t{\n\t\t\t\t\ttype: 'epicshop:test-step-update',\n\t\t\t\t\tstatus: 'pass',\n\t\t\t\t\ttitle: titleString,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t\t'*',\n\t\t\t)\n\t\t}\n\t\treturn result\n\t} catch (e: unknown) {\n\t\tcaughtError = e\n\t}\n\n\tconst error = isError(caughtError)\n\t\t? caughtError\n\t\t: new Error(typeof caughtError === 'string' ? caughtError : 'Unknown error')\n\tconst titleString =\n\t\ttypeof title === 'function' ? title({ type: 'fail', error }) : title\n\terror.message = `${titleString}${error.message ? `\\n\\n${error.message}` : ''}`\n\tthrow error\n}\n"]}
|