@epic-web/workshop-utils 4.5.1 → 4.6.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 +6 -0
- package/dist/esm/apps.server.d.ts.map +1 -1
- package/dist/esm/apps.server.js +41 -27
- package/dist/esm/apps.server.js.map +1 -1
- package/dist/esm/cache.server.js +2 -2
- 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 +9 -9
- package/dist/esm/codefile-mdx.server.js.map +1 -1
- package/dist/esm/compile-mdx.server.js +5 -5
- package/dist/esm/compile-mdx.server.js.map +1 -1
- package/dist/esm/db.server.js +1 -1
- package/dist/esm/db.server.js.map +1 -1
- package/dist/esm/playwright.server.js +8 -8
- package/dist/esm/playwright.server.js.map +1 -1
- package/dist/esm/process-manager.server.js +10 -10
- package/dist/esm/process-manager.server.js.map +1 -1
- package/dist/esm/test.js +1 -1
- package/dist/esm/test.js.map +1 -1
- package/dist/esm/timing.server.js +2 -2
- package/dist/esm/timing.server.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 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
|
+
{"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\t(v) => ['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) =>\n\t\t\t\t\tstr ? (str.split(',') as unknown as AppTypes) : [],\n\t\t\t\t)\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"]}
|
|
@@ -124,11 +124,11 @@ export async function compileMdx(file, { request, forceFresh } = {}) {
|
|
|
124
124
|
[remarkAutolinkHeadings, { behavior: 'wrap' }],
|
|
125
125
|
gfm,
|
|
126
126
|
() => (tree) => {
|
|
127
|
-
visit(tree, 'heading', node => {
|
|
127
|
+
visit(tree, 'heading', (node) => {
|
|
128
128
|
if (title)
|
|
129
129
|
return;
|
|
130
130
|
if (node.depth === 1) {
|
|
131
|
-
visit(node, 'text', textNode => {
|
|
131
|
+
visit(node, 'text', (textNode) => {
|
|
132
132
|
title = textNode.value.trim();
|
|
133
133
|
});
|
|
134
134
|
}
|
|
@@ -136,10 +136,10 @@ export async function compileMdx(file, { request, forceFresh } = {}) {
|
|
|
136
136
|
title = title ? title.replace(/^\d+\. /, '').trim() : null;
|
|
137
137
|
},
|
|
138
138
|
() => (tree) => {
|
|
139
|
-
visit(tree, 'mdxJsxFlowElement', jsxEl => {
|
|
139
|
+
visit(tree, 'mdxJsxFlowElement', (jsxEl) => {
|
|
140
140
|
if (jsxEl.name !== 'EpicVideo')
|
|
141
141
|
return;
|
|
142
|
-
const urlAttr = jsxEl.attributes.find(a => a.type === 'mdxJsxAttribute' && a.name === 'url');
|
|
142
|
+
const urlAttr = jsxEl.attributes.find((a) => a.type === 'mdxJsxAttribute' && a.name === 'url');
|
|
143
143
|
if (!urlAttr)
|
|
144
144
|
return;
|
|
145
145
|
let url = urlAttr.value;
|
|
@@ -237,7 +237,7 @@ async function updateEmbeddedFilesCache({ mdxFile, embeddedFiles, }) {
|
|
|
237
237
|
// make sure we get clean list before updating it
|
|
238
238
|
if (cachedList) {
|
|
239
239
|
for (const [key, value] of Object.entries(cachedList)) {
|
|
240
|
-
cachedList[key] = value.filter(item => item !== mdxFile);
|
|
240
|
+
cachedList[key] = value.filter((item) => item !== mdxFile);
|
|
241
241
|
if (cachedList[key]?.length === 0) {
|
|
242
242
|
delete cachedList[key];
|
|
243
243
|
}
|
|
@@ -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\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"]}
|
|
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\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\t(a) => a.type === 'mdxJsxAttribute' && a.name === 'url',\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (!urlAttr) return\n\t\t\t\t\t\t\tlet url = urlAttr.value\n\t\t\t\t\t\t\tif (typeof url !== 'string') return\n\t\t\t\t\t\t\tif (url.endsWith('/')) url = url.slice(0, -1)\n\t\t\t\t\t\t\tepicVideoEmbeds.push(url)\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t\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.js
CHANGED
|
@@ -50,7 +50,7 @@ const AuthInfoSchema = z
|
|
|
50
50
|
email: z.string(),
|
|
51
51
|
name: z.string().nullable().optional(),
|
|
52
52
|
})
|
|
53
|
-
.transform(d => ({ ...d, id: md5(d.email) }));
|
|
53
|
+
.transform((d) => ({ ...d, id: md5(d.email) }));
|
|
54
54
|
const DataSchema = z.object({
|
|
55
55
|
onboarding: z
|
|
56
56
|
.object({ finishedTourVideo: z.boolean() })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.server.js","sourceRoot":"","sources":["../../src/db.server.ts"],"names":[],"mappings":"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","sourcesContent":["import os from 'os'\nimport path from 'path'\nimport { redirect } from '@remix-run/node'\nimport fsExtra from 'fs-extra'\nimport md5 from 'md5-hex'\nimport { z } from 'zod'\n\nexport const DiscordMemberSchema = z.object({\n\tavatarURL: z.string().nullable().optional(),\n\tdisplayName: z.string(),\n\tid: z.string(),\n})\n\nconst TokenSetSchema = z.object({\n\taccess_token: z.string(),\n\ttoken_type: z.string(),\n\tscope: z.string(),\n})\nexport const PlayerPreferencesSchema = z\n\t.object({\n\t\tvolumeRate: z.number().optional(),\n\t\tplaybackRate: z.number().optional(),\n\t\tautoplay: z.boolean().optional(),\n\t\tsubtitle: z\n\t\t\t.object({\n\t\t\t\tid: z.string().nullable().default(null),\n\t\t\t\tmode: z\n\t\t\t\t\t.literal('disabled')\n\t\t\t\t\t.or(z.literal('hidden'))\n\t\t\t\t\t.or(z.literal('showing'))\n\t\t\t\t\t.nullable()\n\t\t\t\t\t.default('disabled'),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.default({}),\n\t\tmuted: z.boolean().optional(),\n\t\ttheater: z.boolean().optional(),\n\t\tdefaultView: z.string().optional(),\n\t\tactiveSidebarTab: z.number().optional(),\n\t})\n\t.optional()\n\t.default({})\n\nconst PresencePreferencesSchema = z\n\t.object({\n\t\toptOut: z.boolean(),\n\t})\n\t.optional()\n\t.default({ optOut: false })\n\nconst AuthInfoSchema = z\n\t.object({\n\t\ttokenSet: TokenSetSchema,\n\t\temail: z.string(),\n\t\tname: z.string().nullable().optional(),\n\t})\n\t.transform(d => ({ ...d, id: md5(d.email) }))\n\nconst DataSchema = z.object({\n\tonboarding: z\n\t\t.object({ finishedTourVideo: z.boolean() })\n\t\t.optional()\n\t\t.default({ finishedTourVideo: false }),\n\tpreferences: z\n\t\t.object({\n\t\t\tplayer: PlayerPreferencesSchema,\n\t\t\tpresence: PresencePreferencesSchema,\n\t\t})\n\t\t.optional()\n\t\t.default({}),\n\tauthInfo: AuthInfoSchema.optional(),\n\tdiscordMember: DiscordMemberSchema.optional(),\n})\n\nconst appDir = path.join(os.homedir(), '.epicshop')\nconst dbPath = path.join(appDir, 'data.json')\n\nexport async function deleteDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (await fsExtra.exists(dbPath)) {\n\t\t\tawait fsExtra.remove(dbPath)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(`Error deleting the database in ${dbPath}`, error)\n\t}\n}\n\nasync function readDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (await fsExtra.exists(dbPath)) {\n\t\t\tconst db = DataSchema.parse(await fsExtra.readJSON(dbPath))\n\t\t\treturn db\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`Error reading the database in ${dbPath}, moving it to a .bkp file to avoid parsing errors in the future`,\n\t\t\terror,\n\t\t)\n\t\tvoid fsExtra.move(dbPath, `${dbPath}.bkp`).catch(() => {})\n\t}\n\treturn null\n}\n\nexport async function getAuthInfo() {\n\tconst data = await readDb()\n\treturn data?.authInfo ?? null\n}\n\nexport async function getUserInfo() {\n\tconst db = await readDb()\n\tif (!db?.authInfo) return null\n\n\treturn {\n\t\tid: db.authInfo.id,\n\t\tname: db.discordMember?.displayName ?? db.authInfo.name ?? null,\n\t\temail: db.authInfo.email,\n\t\tavatarUrl:\n\t\t\tdb.discordMember?.avatarURL ??\n\t\t\tgetGravatar({ email: db.authInfo.email, size: 288 }),\n\t}\n}\n\nfunction getGravatar({ email, size }: { email: string; size: number }) {\n\tconst gravatarOptions = new URLSearchParams({\n\t\tsize: size.toString(),\n\t\tdefault: 'identicon',\n\t})\n\tconst gravatarUrl = `https://www.gravatar.com/avatar/${md5(\n\t\temail,\n\t)}?${gravatarOptions.toString()}`\n\treturn gravatarUrl\n}\n\nexport async function requireAuthInfo({\n\trequest,\n\tredirectTo,\n}: {\n\trequest: Request\n\tredirectTo?: string | null\n}) {\n\tconst authInfo = await getAuthInfo()\n\tif (!authInfo) {\n\t\tconst requestUrl = new URL(request.url)\n\t\tredirectTo =\n\t\t\tredirectTo === null\n\t\t\t\t? null\n\t\t\t\t: redirectTo ?? `${requestUrl.pathname}${requestUrl.search}`\n\t\tconst loginParams = redirectTo ? new URLSearchParams({ redirectTo }) : null\n\t\tconst loginRedirect = ['/login', loginParams?.toString()]\n\t\t\t.filter(Boolean)\n\t\t\t.join('?')\n\t\tthrow redirect(loginRedirect)\n\t}\n\treturn authInfo\n}\n\nexport async function setAuthInfo({\n\ttokenSet,\n\temail = 'unknown@example.com',\n\tname,\n}: {\n\ttokenSet: Partial<z.infer<typeof TokenSetSchema>>\n\temail?: string\n\tname?: string\n}) {\n\tconst data = await readDb()\n\tconst authInfo = AuthInfoSchema.parse({ tokenSet, email, name })\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, { ...data, authInfo })\n\treturn authInfo\n}\n\nexport async function getPreferences() {\n\tconst data = await readDb()\n\treturn data?.preferences ?? null\n}\n\nexport async function setPlayerPreferences(\n\tplayerPreferences: z.input<typeof PlayerPreferencesSchema>,\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: { ...data?.preferences, player: playerPreferences },\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.preferences.player\n}\n\nexport async function setPresencePreferences(\n\tpresnecePreferences: z.input<typeof PresencePreferencesSchema>,\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: { ...data?.preferences, presence: presnecePreferences },\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.preferences.presence\n}\n\nexport async function getDiscordMember() {\n\tconst data = await readDb()\n\treturn data?.discordMember ?? null\n}\n\nexport async function setDiscordMember(\n\tdiscordMember: z.infer<typeof DiscordMemberSchema>,\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tdiscordMember,\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.discordMember\n}\n\nexport async function deleteDiscordInfo() {\n\tconst data = await readDb()\n\tdelete data?.discordMember\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, data)\n}\n\nexport async function readOnboardingData() {\n\tconst data = await readDb()\n\treturn data?.onboarding ?? null\n}\n\nexport async function updateOnboardingData(onboardingData: {\n\tfinishedTourVideo: boolean\n}) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tonboarding: { ...data?.onboarding, ...onboardingData },\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.onboarding\n}\n"]}
|
|
1
|
+
{"version":3,"file":"db.server.js","sourceRoot":"","sources":["../../src/db.server.ts"],"names":[],"mappings":"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","sourcesContent":["import os from 'os'\nimport path from 'path'\nimport { redirect } from '@remix-run/node'\nimport fsExtra from 'fs-extra'\nimport md5 from 'md5-hex'\nimport { z } from 'zod'\n\nexport const DiscordMemberSchema = z.object({\n\tavatarURL: z.string().nullable().optional(),\n\tdisplayName: z.string(),\n\tid: z.string(),\n})\n\nconst TokenSetSchema = z.object({\n\taccess_token: z.string(),\n\ttoken_type: z.string(),\n\tscope: z.string(),\n})\nexport const PlayerPreferencesSchema = z\n\t.object({\n\t\tvolumeRate: z.number().optional(),\n\t\tplaybackRate: z.number().optional(),\n\t\tautoplay: z.boolean().optional(),\n\t\tsubtitle: z\n\t\t\t.object({\n\t\t\t\tid: z.string().nullable().default(null),\n\t\t\t\tmode: z\n\t\t\t\t\t.literal('disabled')\n\t\t\t\t\t.or(z.literal('hidden'))\n\t\t\t\t\t.or(z.literal('showing'))\n\t\t\t\t\t.nullable()\n\t\t\t\t\t.default('disabled'),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.default({}),\n\t\tmuted: z.boolean().optional(),\n\t\ttheater: z.boolean().optional(),\n\t\tdefaultView: z.string().optional(),\n\t\tactiveSidebarTab: z.number().optional(),\n\t})\n\t.optional()\n\t.default({})\n\nconst PresencePreferencesSchema = z\n\t.object({\n\t\toptOut: z.boolean(),\n\t})\n\t.optional()\n\t.default({ optOut: false })\n\nconst AuthInfoSchema = z\n\t.object({\n\t\ttokenSet: TokenSetSchema,\n\t\temail: z.string(),\n\t\tname: z.string().nullable().optional(),\n\t})\n\t.transform((d) => ({ ...d, id: md5(d.email) }))\n\nconst DataSchema = z.object({\n\tonboarding: z\n\t\t.object({ finishedTourVideo: z.boolean() })\n\t\t.optional()\n\t\t.default({ finishedTourVideo: false }),\n\tpreferences: z\n\t\t.object({\n\t\t\tplayer: PlayerPreferencesSchema,\n\t\t\tpresence: PresencePreferencesSchema,\n\t\t})\n\t\t.optional()\n\t\t.default({}),\n\tauthInfo: AuthInfoSchema.optional(),\n\tdiscordMember: DiscordMemberSchema.optional(),\n})\n\nconst appDir = path.join(os.homedir(), '.epicshop')\nconst dbPath = path.join(appDir, 'data.json')\n\nexport async function deleteDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (await fsExtra.exists(dbPath)) {\n\t\t\tawait fsExtra.remove(dbPath)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(`Error deleting the database in ${dbPath}`, error)\n\t}\n}\n\nasync function readDb() {\n\tif (process.env.EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (await fsExtra.exists(dbPath)) {\n\t\t\tconst db = DataSchema.parse(await fsExtra.readJSON(dbPath))\n\t\t\treturn db\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`Error reading the database in ${dbPath}, moving it to a .bkp file to avoid parsing errors in the future`,\n\t\t\terror,\n\t\t)\n\t\tvoid fsExtra.move(dbPath, `${dbPath}.bkp`).catch(() => {})\n\t}\n\treturn null\n}\n\nexport async function getAuthInfo() {\n\tconst data = await readDb()\n\treturn data?.authInfo ?? null\n}\n\nexport async function getUserInfo() {\n\tconst db = await readDb()\n\tif (!db?.authInfo) return null\n\n\treturn {\n\t\tid: db.authInfo.id,\n\t\tname: db.discordMember?.displayName ?? db.authInfo.name ?? null,\n\t\temail: db.authInfo.email,\n\t\tavatarUrl:\n\t\t\tdb.discordMember?.avatarURL ??\n\t\t\tgetGravatar({ email: db.authInfo.email, size: 288 }),\n\t}\n}\n\nfunction getGravatar({ email, size }: { email: string; size: number }) {\n\tconst gravatarOptions = new URLSearchParams({\n\t\tsize: size.toString(),\n\t\tdefault: 'identicon',\n\t})\n\tconst gravatarUrl = `https://www.gravatar.com/avatar/${md5(\n\t\temail,\n\t)}?${gravatarOptions.toString()}`\n\treturn gravatarUrl\n}\n\nexport async function requireAuthInfo({\n\trequest,\n\tredirectTo,\n}: {\n\trequest: Request\n\tredirectTo?: string | null\n}) {\n\tconst authInfo = await getAuthInfo()\n\tif (!authInfo) {\n\t\tconst requestUrl = new URL(request.url)\n\t\tredirectTo =\n\t\t\tredirectTo === null\n\t\t\t\t? null\n\t\t\t\t: redirectTo ?? `${requestUrl.pathname}${requestUrl.search}`\n\t\tconst loginParams = redirectTo ? new URLSearchParams({ redirectTo }) : null\n\t\tconst loginRedirect = ['/login', loginParams?.toString()]\n\t\t\t.filter(Boolean)\n\t\t\t.join('?')\n\t\tthrow redirect(loginRedirect)\n\t}\n\treturn authInfo\n}\n\nexport async function setAuthInfo({\n\ttokenSet,\n\temail = 'unknown@example.com',\n\tname,\n}: {\n\ttokenSet: Partial<z.infer<typeof TokenSetSchema>>\n\temail?: string\n\tname?: string\n}) {\n\tconst data = await readDb()\n\tconst authInfo = AuthInfoSchema.parse({ tokenSet, email, name })\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, { ...data, authInfo })\n\treturn authInfo\n}\n\nexport async function getPreferences() {\n\tconst data = await readDb()\n\treturn data?.preferences ?? null\n}\n\nexport async function setPlayerPreferences(\n\tplayerPreferences: z.input<typeof PlayerPreferencesSchema>,\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: { ...data?.preferences, player: playerPreferences },\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.preferences.player\n}\n\nexport async function setPresencePreferences(\n\tpresnecePreferences: z.input<typeof PresencePreferencesSchema>,\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tpreferences: { ...data?.preferences, presence: presnecePreferences },\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.preferences.presence\n}\n\nexport async function getDiscordMember() {\n\tconst data = await readDb()\n\treturn data?.discordMember ?? null\n}\n\nexport async function setDiscordMember(\n\tdiscordMember: z.infer<typeof DiscordMemberSchema>,\n) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tdiscordMember,\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.discordMember\n}\n\nexport async function deleteDiscordInfo() {\n\tconst data = await readDb()\n\tdelete data?.discordMember\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, data)\n}\n\nexport async function readOnboardingData() {\n\tconst data = await readDb()\n\treturn data?.onboarding ?? null\n}\n\nexport async function updateOnboardingData(onboardingData: {\n\tfinishedTourVideo: boolean\n}) {\n\tconst data = await readDb()\n\tconst updatedData = {\n\t\t...data,\n\t\tonboarding: { ...data?.onboarding, ...onboardingData },\n\t}\n\tawait fsExtra.ensureDir(appDir)\n\tawait fsExtra.writeJSON(dbPath, updatedData)\n\treturn updatedData.onboarding\n}\n"]}
|
|
@@ -5,12 +5,12 @@ import { getApps, isProblemApp } from './apps.server.js';
|
|
|
5
5
|
export async function getInBrowserTestPages() {
|
|
6
6
|
const apps = (await getApps())
|
|
7
7
|
.filter(isProblemApp)
|
|
8
|
-
.filter(a => a.test.type === 'browser');
|
|
9
|
-
const pages = apps.map(app => {
|
|
8
|
+
.filter((a) => a.test.type === 'browser');
|
|
9
|
+
const pages = apps.map((app) => {
|
|
10
10
|
if (app.test.type !== 'browser')
|
|
11
11
|
return null;
|
|
12
12
|
const { pathname } = app.test;
|
|
13
|
-
return app.test.testFiles.map(testFile => {
|
|
13
|
+
return app.test.testFiles.map((testFile) => {
|
|
14
14
|
return {
|
|
15
15
|
path: `${pathname}${testFile}`,
|
|
16
16
|
testFile,
|
|
@@ -19,7 +19,7 @@ export async function getInBrowserTestPages() {
|
|
|
19
19
|
});
|
|
20
20
|
return pages.filter(Boolean).flat();
|
|
21
21
|
}
|
|
22
|
-
const sleep = (time) => new Promise(resolve => setTimeout(resolve, time));
|
|
22
|
+
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
23
23
|
async function waitFor(cb, { timeout = 1000, interval = 30 } = {}) {
|
|
24
24
|
const timeEnd = Date.now() + timeout;
|
|
25
25
|
let lastError = null;
|
|
@@ -54,7 +54,7 @@ export function setupInBrowserTests() {
|
|
|
54
54
|
const errors = [];
|
|
55
55
|
const logs = [];
|
|
56
56
|
const infos = [];
|
|
57
|
-
page.on('console', message => {
|
|
57
|
+
page.on('console', (message) => {
|
|
58
58
|
switch (message.type()) {
|
|
59
59
|
case 'error': {
|
|
60
60
|
errors.push(message.text());
|
|
@@ -75,14 +75,14 @@ export function setupInBrowserTests() {
|
|
|
75
75
|
});
|
|
76
76
|
await page.goto(testPage.path);
|
|
77
77
|
await page.waitForLoadState();
|
|
78
|
-
await waitFor(() => infos.find(info => info.includes('status: pending')), { timeout: 10_000 });
|
|
78
|
+
await waitFor(() => infos.find((info) => info.includes('status: pending')), { timeout: 10_000 });
|
|
79
79
|
const result = await Promise.race([
|
|
80
|
-
waitFor(() => logs.find(log => log.includes('status: pass')), {
|
|
80
|
+
waitFor(() => logs.find((log) => log.includes('status: pass')), {
|
|
81
81
|
timeout: 10_000,
|
|
82
82
|
}),
|
|
83
83
|
waitFor(() => (errors.length > 0 ? errors : null), {
|
|
84
84
|
timeout: 10_000,
|
|
85
|
-
}).then(errors => {
|
|
85
|
+
}).then((errors) => {
|
|
86
86
|
throw errors;
|
|
87
87
|
}),
|
|
88
88
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright.server.js","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,UAAU,MAAM,aAAa,CAAA;AACpC,OAAO,CAAC,MAAM,KAAK,CAAA;AACnB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAExD,MAAM,CAAC,KAAK,UAAU,qBAAqB;IAC1C,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,EAAE,CAAC;SAC5B,MAAM,CAAC,YAAY,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;
|
|
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"]}
|
|
@@ -61,7 +61,7 @@ export async function runAppDev(app) {
|
|
|
61
61
|
if (!(await isPortAvailable(portNumber))) {
|
|
62
62
|
return { status: 'port-unavailable', running: false, portNumber };
|
|
63
63
|
}
|
|
64
|
-
const availableColors = colors.filter(color => Array.from(devProcesses.values()).every(p => p.color !== color));
|
|
64
|
+
const availableColors = colors.filter((color) => Array.from(devProcesses.values()).every((p) => p.color !== color));
|
|
65
65
|
const color = availableColors[devProcesses.size % availableColors.length] ?? 'blue';
|
|
66
66
|
const appProcess = spawn('npm', ['run', 'dev'], {
|
|
67
67
|
cwd: app.fullPath,
|
|
@@ -83,7 +83,7 @@ export async function runAppDev(app) {
|
|
|
83
83
|
console.log(data
|
|
84
84
|
.toString('utf-8')
|
|
85
85
|
.split('\n')
|
|
86
|
-
.map(line => `${prefix} ${line}`)
|
|
86
|
+
.map((line) => `${prefix} ${line}`)
|
|
87
87
|
.join('\n'));
|
|
88
88
|
}
|
|
89
89
|
appProcess.stdout.on('data', handleStdOutData);
|
|
@@ -91,12 +91,12 @@ export async function runAppDev(app) {
|
|
|
91
91
|
console.error(data
|
|
92
92
|
.toString('utf-8')
|
|
93
93
|
.split('\n')
|
|
94
|
-
.map(line => `${prefix} ${line}`)
|
|
94
|
+
.map((line) => `${prefix} ${line}`)
|
|
95
95
|
.join('\n'));
|
|
96
96
|
}
|
|
97
97
|
appProcess.stderr.on('data', handleStdErrData);
|
|
98
98
|
devProcesses.set(key, { color, process: appProcess, port: portNumber });
|
|
99
|
-
appProcess.on('exit', code => {
|
|
99
|
+
appProcess.on('exit', (code) => {
|
|
100
100
|
appProcess.stdout.off('data', handleStdOutData);
|
|
101
101
|
appProcess.stderr.off('data', handleStdErrData);
|
|
102
102
|
console.log(`${prefix} exited (${code})`);
|
|
@@ -144,7 +144,7 @@ export async function runAppTests(app) {
|
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
146
|
testProcess.stderr?.on('data', handleStdErrData);
|
|
147
|
-
void testProcess.on('exit', code => {
|
|
147
|
+
void testProcess.on('exit', (code) => {
|
|
148
148
|
testProcess.stdout?.off('data', handleStdOutData);
|
|
149
149
|
testProcess.stderr?.off('data', handleStdErrData);
|
|
150
150
|
// don't delete the entry from the map so we can show the output at any time
|
|
@@ -170,7 +170,7 @@ export async function waitOnApp(app) {
|
|
|
170
170
|
}
|
|
171
171
|
catch (error) {
|
|
172
172
|
lastError = error;
|
|
173
|
-
await new Promise(resolve => setTimeout(resolve, retryInterval));
|
|
173
|
+
await new Promise((resolve) => setTimeout(resolve, retryInterval));
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
return { status: 'error', error: getErrorMessage(lastError) };
|
|
@@ -178,7 +178,7 @@ export async function waitOnApp(app) {
|
|
|
178
178
|
return null;
|
|
179
179
|
}
|
|
180
180
|
export function isPortAvailable(port) {
|
|
181
|
-
return new Promise(resolve => {
|
|
181
|
+
return new Promise((resolve) => {
|
|
182
182
|
const server = net.createServer();
|
|
183
183
|
server.unref();
|
|
184
184
|
server.on('error', () => resolve(false));
|
|
@@ -229,7 +229,7 @@ export async function closeProcess(key) {
|
|
|
229
229
|
throw new Error('cannot close processes in deployed mode');
|
|
230
230
|
const proc = devProcesses.get(key);
|
|
231
231
|
if (proc) {
|
|
232
|
-
const exitedPromise = new Promise(resolve => proc.process.on('exit', resolve));
|
|
232
|
+
const exitedPromise = new Promise((resolve) => proc.process.on('exit', resolve));
|
|
233
233
|
if (process.platform === 'win32') {
|
|
234
234
|
const { execa } = await import('execa');
|
|
235
235
|
await execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/t']);
|
|
@@ -238,14 +238,14 @@ export async function closeProcess(key) {
|
|
|
238
238
|
proc.process.kill();
|
|
239
239
|
}
|
|
240
240
|
await Promise.race([
|
|
241
|
-
new Promise(resolve => setTimeout(resolve, 500)),
|
|
241
|
+
new Promise((resolve) => setTimeout(resolve, 500)),
|
|
242
242
|
exitedPromise,
|
|
243
243
|
]);
|
|
244
244
|
await stopPort(proc.port); // just in case 🤷♂️
|
|
245
245
|
devProcesses.delete(key);
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
-
const sleep = (t) => new Promise(resolve => setTimeout(resolve, t));
|
|
248
|
+
const sleep = (t) => new Promise((resolve) => setTimeout(resolve, t));
|
|
249
249
|
export async function stopPort(port) {
|
|
250
250
|
if (isDeployed)
|
|
251
251
|
throw new Error('cannot stop ports in deployed mode');
|