@epic-web/workshop-utils 6.11.2 → 6.11.4

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.
@@ -361,7 +361,7 @@ export type WorkshopConfig = z.infer<typeof WorkshopConfigSchema>;
361
361
  * Generate a URL with subdomain support
362
362
  * Only applies subdomain logic when not deployed
363
363
  */
364
- export declare function getWorkshopUrl(port: number, subdomain?: string): Promise<string>;
364
+ export declare function getWorkshopUrl(port: number, subdomain?: string): string;
365
365
  export declare function getWorkshopConfig(): WorkshopConfig;
366
366
  export declare function getStackBlitzUrl({ fullPath, title, type, }: {
367
367
  fullPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.server.d.ts","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,eAAe,cACsB,CAAA;AAgDlD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAcjC,CAAA;AAUF,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkFvB,CAAA;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAiCjE;;;GAGG;AACH,wBAAsB,cAAc,CACnC,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAqClD;AAED,wBAAsB,gBAAgB,CAAC,EACtC,QAAQ,EACR,KAAK,EACL,IAAI,GACJ,EAAE;IACF,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACZ,0BAuEA;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;GA0ElD"}
1
+ {"version":3,"file":"config.server.d.ts","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,eAAe,cACsB,CAAA;AAIlD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAcjC,CAAA;AAUF,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkFvB,CAAA;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAiCjE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAuCvE;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAqClD;AAED,wBAAsB,gBAAgB,CAAC,EACtC,QAAQ,EACR,KAAK,EACL,IAAI,GACJ,EAAE;IACF,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACZ,0BAuEA;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;GA0ElD"}
@@ -1,47 +1,9 @@
1
- import dns from 'node:dns';
2
1
  import fs from 'node:fs';
3
2
  import path from 'node:path';
4
- import { promisify } from 'node:util';
5
3
  import { z } from 'zod';
6
4
  import { handleGitHubRepoAndRoot } from './utils.js';
7
- const dnsLookup = promisify(dns.lookup);
8
5
  export const getWorkshopRoot = () => process.env.EPICSHOP_CONTEXT_CWD ?? process.cwd();
9
6
  const getRootPkgJsonPath = () => path.join(getWorkshopRoot(), 'package.json');
10
- // Cache for subdomain resolution check
11
- const subdomainResolutionCache = {
12
- checked: false,
13
- supportsSubdomains: false,
14
- };
15
- /**
16
- * Check if the system supports subdomain resolution on localhost
17
- * This check only happens once on startup by attempting to resolve a test subdomain
18
- */
19
- async function checkSubdomainSupport() {
20
- if (subdomainResolutionCache.checked) {
21
- return subdomainResolutionCache.supportsSubdomains;
22
- }
23
- // If a check is already in progress, return that promise
24
- if (subdomainResolutionCache.checkPromise) {
25
- return subdomainResolutionCache.checkPromise;
26
- }
27
- // Start the check and cache the promise
28
- subdomainResolutionCache.checkPromise = (async () => {
29
- try {
30
- // Try to resolve a test subdomain
31
- // We use 'test.localhost' as it's a safe test domain
32
- await dnsLookup('test.localhost');
33
- subdomainResolutionCache.supportsSubdomains = true;
34
- }
35
- catch (error) {
36
- // If the error is ENOTFOUND or any other DNS error,
37
- // subdomain resolution likely isn't supported
38
- subdomainResolutionCache.supportsSubdomains = false;
39
- }
40
- subdomainResolutionCache.checked = true;
41
- return subdomainResolutionCache.supportsSubdomains;
42
- })();
43
- return subdomainResolutionCache.checkPromise;
44
- }
45
7
  export const StackBlitzConfigSchema = z.object({
46
8
  // we default this to `${exerciseTitle} (${type})`
47
9
  title: z.string().optional(),
@@ -164,7 +126,7 @@ function readRootPkgJson() {
164
126
  * Generate a URL with subdomain support
165
127
  * Only applies subdomain logic when not deployed
166
128
  */
167
- export async function getWorkshopUrl(port, subdomain) {
129
+ export function getWorkshopUrl(port, subdomain) {
168
130
  // Check if deployed - use process.env directly since ENV might not be initialized yet
169
131
  const isDeployed = process.env.EPICSHOP_DEPLOYED === 'true' ||
170
132
  process.env.EPICSHOP_DEPLOYED === '1';
@@ -193,10 +155,7 @@ export async function getWorkshopUrl(port, subdomain) {
193
155
  }
194
156
  }
195
157
  if (subdomainToUse) {
196
- const supportsSubdomains = await checkSubdomainSupport();
197
- if (supportsSubdomains) {
198
- return `http://${subdomainToUse}.localhost:${port}`;
199
- }
158
+ return `http://${subdomainToUse}.localhost:${port}`;
200
159
  }
201
160
  }
202
161
  return `http://localhost:${port}`;
@@ -1 +1 @@
1
- {"version":3,"file":"config.server.js","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"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","sourcesContent":["import dns from 'node:dns'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\nimport { z } from 'zod'\nimport { handleGitHubRepoAndRoot } from './utils.js'\n\nconst dnsLookup = promisify(dns.lookup)\n\nexport const getWorkshopRoot = () =>\n\tprocess.env.EPICSHOP_CONTEXT_CWD ?? process.cwd()\n\nconst getRootPkgJsonPath = () => path.join(getWorkshopRoot(), 'package.json')\n\n// Cache for subdomain resolution check\nconst subdomainResolutionCache: {\n\tchecked: boolean\n\tsupportsSubdomains: boolean\n\tcheckPromise?: Promise<boolean>\n} = {\n\tchecked: false,\n\tsupportsSubdomains: false,\n}\n\n/**\n * Check if the system supports subdomain resolution on localhost\n * This check only happens once on startup by attempting to resolve a test subdomain\n */\nasync function checkSubdomainSupport(): Promise<boolean> {\n\tif (subdomainResolutionCache.checked) {\n\t\treturn subdomainResolutionCache.supportsSubdomains\n\t}\n\n\t// If a check is already in progress, return that promise\n\tif (subdomainResolutionCache.checkPromise) {\n\t\treturn subdomainResolutionCache.checkPromise\n\t}\n\n\t// Start the check and cache the promise\n\tsubdomainResolutionCache.checkPromise = (async () => {\n\t\ttry {\n\t\t\t// Try to resolve a test subdomain\n\t\t\t// We use 'test.localhost' as it's a safe test domain\n\t\t\tawait dnsLookup('test.localhost')\n\t\t\tsubdomainResolutionCache.supportsSubdomains = true\n\t\t} catch (error: any) {\n\t\t\t// If the error is ENOTFOUND or any other DNS error,\n\t\t\t// subdomain resolution likely isn't supported\n\t\t\tsubdomainResolutionCache.supportsSubdomains = false\n\t\t}\n\n\t\tsubdomainResolutionCache.checked = true\n\t\treturn subdomainResolutionCache.supportsSubdomains\n\t})()\n\n\treturn subdomainResolutionCache.checkPromise\n}\n\nexport const StackBlitzConfigSchema = z.object({\n\t// we default this to `${exerciseTitle} (${type})`\n\ttitle: z.string().optional(),\n\t// stackblitz defaults this to dev automatically\n\tstartScript: z.string().optional(),\n\t// if no value is provided, then stackblitz defaults this to whatever\n\t// looks best based on the width of the screen\n\tview: z\n\t\t.union([z.literal('editor'), z.literal('preview'), z.literal('both')])\n\t\t.optional(),\n\tfile: z.string().optional(),\n\thidedevtools: z.string().optional(),\n\tterminalHeight: z.string().optional(),\n\thideNavigation: z.string().optional(),\n})\n\nconst InstructorSchema = z.object({\n\tname: z.string().optional(),\n\tavatar: z.string().optional(),\n\t𝕏: z.string().optional(),\n\txHandle: z.string().optional(),\n})\n\n// most defaults are for backwards compatibility\nconst WorkshopConfigSchema = z\n\t.object({\n\t\ttitle: z.string(),\n\t\tsubtitle: z.string().optional(),\n\t\tinstructor: InstructorSchema.optional(),\n\t\tepicWorkshopHost: z.string().optional(),\n\t\tepicWorkshopSlug: z.string().optional(),\n\t\tsubdomain: z.string().optional(),\n\t\tproduct: z\n\t\t\t.object({\n\t\t\t\thost: z.string().default('www.epicweb.dev'),\n\t\t\t\tdisplayName: z.string().default('EpicWeb.dev'),\n\t\t\t\tdisplayNameShort: z.string().default('Epic Web'),\n\t\t\t\tlogo: z.string().default('/logo.svg'),\n\t\t\t\tslug: z.string().optional(),\n\t\t\t\tdiscordChannelId: z.string().default('1161045224907341972'),\n\t\t\t\tdiscordTags: z.array(z.string()).optional(),\n\t\t\t})\n\t\t\t.default({}),\n\t\tonboardingVideo: z\n\t\t\t.string()\n\t\t\t.default(\n\t\t\t\t'https://www.epicweb.dev/tips/get-started-with-the-epic-workshop-app',\n\t\t\t),\n\t\tgithubRepo: z\n\t\t\t.string()\n\t\t\t.transform((githubRepo) => githubRepo ?? ENV.EPICSHOP_GITHUB_REPO),\n\t\tgithubRoot: z\n\t\t\t.string()\n\t\t\t.transform((githubRoot) => githubRoot ?? ENV.EPICSHOP_GITHUB_ROOT),\n\t\tstackBlitzConfig: StackBlitzConfigSchema.optional(),\n\t\tforms: z\n\t\t\t.object({\n\t\t\t\tworkshop: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.default(\n\t\t\t\t\t\t'https://docs.google.com/forms/d/e/1FAIpQLSdRmj9p8-5zyoqRzxp3UpqSbC3aFkweXvvJIKes0a5s894gzg/viewform?hl=en&embedded=true&entry.2123647600={workshopTitle}',\n\t\t\t\t\t),\n\t\t\t\texercise: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.default(\n\t\t\t\t\t\t'https://docs.google.com/forms/d/e/1FAIpQLSf3o9xyjQepTlOTH5Z7ZwkeSTdXh6YWI_RGc9KiyD3oUN0p6w/viewform?hl=en&embedded=true&entry.1836176234={workshopTitle}&entry.428900931={exerciseTitle}',\n\t\t\t\t\t),\n\t\t\t})\n\t\t\t.default({}),\n\t\ttestTab: z\n\t\t\t.object({\n\t\t\t\tenabled: z.boolean().default(true),\n\t\t\t})\n\t\t\t.default({}),\n\t\tscripts: z\n\t\t\t.object({\n\t\t\t\tpostupdate: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tinitialRoute: z.string().optional().default('/'),\n\t\tnotifications: z\n\t\t\t.array(\n\t\t\t\tz.object({\n\t\t\t\t\tid: z.string(),\n\t\t\t\t\ttitle: z.string(),\n\t\t\t\t\tmessage: z.string(),\n\t\t\t\t\tlink: z.string().optional(),\n\t\t\t\t\ttype: z.enum(['info', 'warning', 'danger']),\n\t\t\t\t\texpiresAt: z.date().nullable(),\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.optional()\n\t\t\t.default([]),\n\t})\n\t.transform((data) => {\n\t\treturn {\n\t\t\t...data,\n\t\t\tproduct: {\n\t\t\t\t...data.product,\n\t\t\t\tdisplayNameShort:\n\t\t\t\t\tdata.product.displayNameShort ?? data.product.displayName,\n\t\t\t\t// for backwards compatibility\n\t\t\t\thost: data.product.host ?? data.epicWorkshopHost,\n\t\t\t\tslug: data.product.slug ?? data.epicWorkshopSlug,\n\t\t\t},\n\t\t}\n\t})\n\nexport type WorkshopConfig = z.infer<typeof WorkshopConfigSchema>\n\nconst configCache: {\n\tconfig: WorkshopConfig | null\n\tmodified: number\n} = {\n\tconfig: null,\n\tmodified: 0,\n}\n\n// Utility to read and parse the root package.json\nfunction readRootPkgJson(): any {\n\tconst packageJsonPath = getRootPkgJsonPath()\n\ttry {\n\t\tconst packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8')\n\t\treturn JSON.parse(packageJsonContent)\n\t} catch (error) {\n\t\tconsole.error(`Error reading or parsing package.json:`, error)\n\t\tif (error instanceof Error && error.message.includes('ENOENT')) {\n\t\t\tthrow new Error(\n\t\t\t\t`package.json not found at ${packageJsonPath}. Please ensure you're running the command from the correct directory.`,\n\t\t\t)\n\t\t} else if (error instanceof SyntaxError) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid JSON in package.json at ${packageJsonPath}. Please check the file for syntax errors.`,\n\t\t\t)\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Could not find and parse package.json at ${packageJsonPath}`,\n\t\t)\n\t}\n}\n\n/**\n * Generate a URL with subdomain support\n * Only applies subdomain logic when not deployed\n */\nexport async function getWorkshopUrl(\n\tport: number,\n\tsubdomain?: string,\n): Promise<string> {\n\t// Check if deployed - use process.env directly since ENV might not be initialized yet\n\tconst isDeployed =\n\t\tprocess.env.EPICSHOP_DEPLOYED === 'true' ||\n\t\tprocess.env.EPICSHOP_DEPLOYED === '1'\n\n\t// Only use subdomain logic when not deployed\n\tif (!isDeployed) {\n\t\tconst config = getWorkshopConfig()\n\t\tlet subdomainToUse = subdomain ?? config.subdomain\n\n\t\t// Fallback to package.json name if subdomain is not set\n\t\tif (!subdomainToUse) {\n\t\t\ttry {\n\t\t\t\tconst packageJson = readRootPkgJson()\n\t\t\t\tif (\n\t\t\t\t\tpackageJson &&\n\t\t\t\t\ttypeof packageJson === 'object' &&\n\t\t\t\t\t'name' in packageJson &&\n\t\t\t\t\ttypeof packageJson.name === 'string'\n\t\t\t\t) {\n\t\t\t\t\tlet name = packageJson.name as string\n\t\t\t\t\t// Sanitize: lowercased, non-alphanumeric to dashes, trim dashes\n\t\t\t\t\tsubdomainToUse = name\n\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t.replace(/[^a-z0-9-]/g, '-')\n\t\t\t\t\t\t.replace(/^-+|-+$/g, '')\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// ignore, fallback to localhost\n\t\t\t}\n\t\t}\n\n\t\tif (subdomainToUse) {\n\t\t\tconst supportsSubdomains = await checkSubdomainSupport()\n\t\t\tif (supportsSubdomains) {\n\t\t\t\treturn `http://${subdomainToUse}.localhost:${port}`\n\t\t\t}\n\t\t}\n\t}\n\n\treturn `http://localhost:${port}`\n}\n\nexport function getWorkshopConfig(): WorkshopConfig {\n\tif (\n\t\tconfigCache.config &&\n\t\tconfigCache.modified > fs.statSync(getRootPkgJsonPath()).mtimeMs\n\t) {\n\t\treturn configCache.config\n\t}\n\n\tconst packageJson = readRootPkgJson()\n\n\tconst epicshopConfig = packageJson.epicshop || {}\n\n\t// Set githubRepo and githubRoot before parsing\n\tconst { githubRepo, githubRoot } = handleGitHubRepoAndRoot({\n\t\tgithubRepo: epicshopConfig.githubRepo,\n\t\tgithubRoot: epicshopConfig.githubRoot,\n\t})\n\tepicshopConfig.githubRepo = githubRepo\n\tepicshopConfig.githubRoot = githubRoot\n\n\ttry {\n\t\tconst parsedConfig = WorkshopConfigSchema.parse(epicshopConfig)\n\t\tconfigCache.config = parsedConfig\n\t\tconfigCache.modified = fs.statSync(getRootPkgJsonPath()).mtimeMs\n\t\treturn parsedConfig\n\t} catch (error) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tconst flattenedErrors = error.flatten()\n\t\t\tconst errorMessages = Object.entries(flattenedErrors.fieldErrors)\n\t\t\t\t.map(([field, errors]) => `${field}: ${errors?.join(', ')}`)\n\t\t\t\t.concat(flattenedErrors.formErrors)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid epicshop configuration in ${getRootPkgJsonPath()}:\\n${errorMessages.join('\\n')}`,\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n\nexport async function getStackBlitzUrl({\n\tfullPath,\n\ttitle,\n\ttype,\n}: {\n\tfullPath: string\n\ttitle: string\n\ttype: string\n}) {\n\tconst workshopConfig = getWorkshopConfig()\n\tconst appConfig = await getAppConfig(fullPath)\n\n\tif (appConfig.stackBlitzConfig === null) return null\n\n\tlet githubRootUrlString = workshopConfig.githubRoot\n\n\tconst githubRootUrl = new URL(\n\t\tgithubRootUrlString.replace(/\\/blob\\//, '/tree/'),\n\t)\n\n\tconst githubPart = githubRootUrl.pathname\n\n\t// Check if package.json exists to determine if this is a simple exercise\n\tconst packageJsonPath = path.join(fullPath, 'package.json')\n\tconst packageJsonExists = await fs.promises\n\t\t.access(packageJsonPath, fs.constants.F_OK)\n\t\t.then(() => true)\n\t\t.catch(() => false)\n\n\tlet stackBlitzConfig = {\n\t\t...appConfig.stackBlitzConfig,\n\t\ttitle: appConfig.stackBlitzConfig?.title ?? `${title} (${type})`,\n\t}\n\n\t// For simple exercises without package.json, configure StackBlitz to show only editor\n\tif (!packageJsonExists) {\n\t\t// Find the first existing file from the priority list\n\t\tconst priorityFiles = [\n\t\t\t'index.html',\n\t\t\t'index.tsx',\n\t\t\t'index.ts',\n\t\t\t'index.jsx',\n\t\t\t'index.js',\n\t\t\t'README.mdx',\n\t\t\t'README.md',\n\t\t]\n\n\t\tlet defaultFile: string | null = null\n\t\tfor (const fileName of priorityFiles) {\n\t\t\tconst filePath = path.join(fullPath, fileName)\n\t\t\ttry {\n\t\t\t\tawait fs.promises.access(filePath, fs.constants.F_OK)\n\t\t\t\tdefaultFile = fileName\n\t\t\t\tbreak\n\t\t\t} catch {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tstackBlitzConfig = {\n\t\t\t...stackBlitzConfig,\n\t\t\tview: 'editor', // Show only editor, no preview or terminal\n\t\t\thidedevtools: '1', // Hide the console/devtools\n\t\t\tterminalHeight: '0', // Hide the terminal completely\n\t\t\thideNavigation: '1', // Hide the preview's URL bar\n\t\t\t...(defaultFile && { file: defaultFile }), // Set default file if found\n\t\t}\n\t}\n\n\tconst params = new URLSearchParams(stackBlitzConfig as Record<string, string>)\n\n\tconst relativePath = fullPath.replace(`${getWorkshopRoot()}${path.sep}`, '')\n\n\tconst stackBlitzUrl = new URL(\n\t\t`/github${githubPart}/${relativePath}?${params}`,\n\t\t'https://stackblitz.com',\n\t)\n\n\treturn stackBlitzUrl.toString()\n}\n\nexport async function getAppConfig(fullPath: string) {\n\tconst workshopConfig = getWorkshopConfig()\n\n\tlet epicshopConfig: Record<string, any> = {}\n\tlet scripts: Record<string, string> = {}\n\n\tconst packageJsonPath = path.join(fullPath, 'package.json')\n\tconst packageJsonExists = await fs.promises\n\t\t.access(packageJsonPath, fs.constants.F_OK)\n\t\t.then(() => true)\n\t\t.catch(() => false)\n\n\tif (packageJsonExists) {\n\t\tconst pkg = JSON.parse(\n\t\t\tawait fs.promises.readFile(path.join(fullPath, 'package.json'), 'utf8'),\n\t\t) as any\n\t\tepicshopConfig = pkg.epicshop ?? {}\n\t\tscripts = pkg.scripts ?? {}\n\t}\n\n\tconst AppConfigSchema = z.object({\n\t\tstackBlitzConfig: StackBlitzConfigSchema.nullable()\n\t\t\t.optional()\n\t\t\t.transform((appStackBlitzConfig) => {\n\t\t\t\tif (appStackBlitzConfig === null) return null\n\n\t\t\t\treturn {\n\t\t\t\t\t...workshopConfig.stackBlitzConfig,\n\t\t\t\t\t...appStackBlitzConfig,\n\t\t\t\t}\n\t\t\t}),\n\t\ttestTab: z\n\t\t\t.object({\n\t\t\t\tenabled: z\n\t\t\t\t\t.boolean()\n\t\t\t\t\t.optional()\n\t\t\t\t\t.default(workshopConfig.testTab?.enabled ?? true),\n\t\t\t})\n\t\t\t.default({}),\n\t\tscripts: z\n\t\t\t.object({\n\t\t\t\ttest: z.string().optional(),\n\t\t\t\tdev: z.string().optional(),\n\t\t\t})\n\t\t\t.default({}),\n\t\tinitialRoute: z.string().optional().default(workshopConfig.initialRoute),\n\t})\n\n\tconst appConfig = {\n\t\tstackBlitzConfig: epicshopConfig.stackBlitzConfig,\n\t\ttestTab: {\n\t\t\tenabled: epicshopConfig.testTab?.enabled,\n\t\t},\n\t\tscripts: {\n\t\t\ttest: scripts.test,\n\t\t\tdev: scripts.dev,\n\t\t},\n\t\tinitialRoute: epicshopConfig.initialRoute,\n\t}\n\n\ttry {\n\t\treturn AppConfigSchema.parse(appConfig)\n\t} catch (error) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tconst flattenedErrors = error.flatten()\n\t\t\tconst errorMessages = Object.entries(flattenedErrors.fieldErrors)\n\t\t\t\t.map(([field, errors]) => `${field}: ${errors?.join(', ')}`)\n\t\t\t\t.concat(flattenedErrors.formErrors)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid app configuration for ${fullPath}:\\n${errorMessages.join('\\n')}`,\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n"]}
1
+ {"version":3,"file":"config.server.js","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAEpD,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE,CACnC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAA;AAElD,MAAM,kBAAkB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,cAAc,CAAC,CAAA;AAE7E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,kDAAkD;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,gDAAgD;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,qEAAqE;IACrE,8CAA8C;IAC9C,IAAI,EAAE,CAAC;SACL,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;SACrE,QAAQ,EAAE;IACZ,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAA;AAEF,gDAAgD;AAChD,MAAM,oBAAoB,GAAG,CAAC;KAC5B,MAAM,CAAC;IACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,UAAU,EAAE,gBAAgB,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,OAAO,EAAE,CAAC;SACR,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;QAC3C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC;QAC9C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;QAChD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;QACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC;QAC3D,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KAC3C,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,eAAe,EAAE,CAAC;SAChB,MAAM,EAAE;SACR,OAAO,CACP,qEAAqE,CACrE;IACF,UAAU,EAAE,CAAC;SACX,MAAM,EAAE;SACR,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,GAAG,CAAC,oBAAoB,CAAC;IACnE,UAAU,EAAE,CAAC;SACX,MAAM,EAAE;SACR,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,GAAG,CAAC,oBAAoB,CAAC;IACnE,gBAAgB,EAAE,sBAAsB,CAAC,QAAQ,EAAE;IACnD,KAAK,EAAE,CAAC;SACN,MAAM,CAAC;QACP,QAAQ,EAAE,CAAC;aACT,MAAM,EAAE;aACR,OAAO,CACP,0JAA0J,CAC1J;QACF,QAAQ,EAAE,CAAC;aACT,MAAM,EAAE;aACR,OAAO,CACP,0LAA0L,CAC1L;KACF,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;SACR,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KAClC,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;SACR,MAAM,CAAC;QACP,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACjC,CAAC;SACD,QAAQ,EAAE;IACZ,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAChD,aAAa,EAAE,CAAC;SACd,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;QACR,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC3C,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;KAC9B,CAAC,CACF;SACA,QAAQ,EAAE;SACV,OAAO,CAAC,EAAE,CAAC;CACb,CAAC;KACD,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;IACnB,OAAO;QACN,GAAG,IAAI;QACP,OAAO,EAAE;YACR,GAAG,IAAI,CAAC,OAAO;YACf,gBAAgB,EACf,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW;YAC1D,8BAA8B;YAC9B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,gBAAgB;YAChD,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,gBAAgB;SAChD;KACD,CAAA;AACF,CAAC,CAAC,CAAA;AAIH,MAAM,WAAW,GAGb;IACH,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,CAAC;CACX,CAAA;AAED,kDAAkD;AAClD,SAAS,eAAe;IACvB,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAA;IAC5C,IAAI,CAAC;QACJ,MAAM,kBAAkB,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;QACnE,OAAO,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAA;QAC9D,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CACd,6BAA6B,eAAe,wEAAwE,CACpH,CAAA;QACF,CAAC;aAAM,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACd,mCAAmC,eAAe,4CAA4C,CAC9F,CAAA;QACF,CAAC;QACD,MAAM,IAAI,KAAK,CACd,4CAA4C,eAAe,EAAE,CAC7D,CAAA;IACF,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,SAAkB;IAC9D,sFAAsF;IACtF,MAAM,UAAU,GACf,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,MAAM;QACxC,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,CAAA;IAEtC,6CAA6C;IAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;QAClC,IAAI,cAAc,GAAG,SAAS,IAAI,MAAM,CAAC,SAAS,CAAA;QAElD,wDAAwD;QACxD,IAAI,CAAC,cAAc,EAAE,CAAC;YACrB,IAAI,CAAC;gBACJ,MAAM,WAAW,GAAG,eAAe,EAAE,CAAA;gBACrC,IACC,WAAW;oBACX,OAAO,WAAW,KAAK,QAAQ;oBAC/B,MAAM,IAAI,WAAW;oBACrB,OAAO,WAAW,CAAC,IAAI,KAAK,QAAQ,EACnC,CAAC;oBACF,IAAI,IAAI,GAAG,WAAW,CAAC,IAAc,CAAA;oBACrC,gEAAgE;oBAChE,cAAc,GAAG,IAAI;yBACnB,WAAW,EAAE;yBACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;yBAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;gBAC1B,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;gBACR,gCAAgC;YACjC,CAAC;QACF,CAAC;QAED,IAAI,cAAc,EAAE,CAAC;YACpB,OAAO,UAAU,cAAc,cAAc,IAAI,EAAE,CAAA;QACpD,CAAC;IACF,CAAC;IAED,OAAO,oBAAoB,IAAI,EAAE,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAChC,IACC,WAAW,CAAC,MAAM;QAClB,WAAW,CAAC,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAC/D,CAAC;QACF,OAAO,WAAW,CAAC,MAAM,CAAA;IAC1B,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,EAAE,CAAA;IAErC,MAAM,cAAc,GAAG,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAA;IAEjD,+CAA+C;IAC/C,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,uBAAuB,CAAC;QAC1D,UAAU,EAAE,cAAc,CAAC,UAAU;QACrC,UAAU,EAAE,cAAc,CAAC,UAAU;KACrC,CAAC,CAAA;IACF,cAAc,CAAC,UAAU,GAAG,UAAU,CAAA;IACtC,cAAc,CAAC,UAAU,GAAG,UAAU,CAAA;IAEtC,IAAI,CAAC;QACJ,MAAM,YAAY,GAAG,oBAAoB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;QAC/D,WAAW,CAAC,MAAM,GAAG,YAAY,CAAA;QACjC,WAAW,CAAC,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAA;QAChE,OAAO,YAAY,CAAA;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,EAAE,CAAA;YACvC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC;iBAC/D,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;iBAC3D,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;YACpC,MAAM,IAAI,KAAK,CACd,qCAAqC,kBAAkB,EAAE,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzF,CAAA;QACF,CAAC;QACD,MAAM,KAAK,CAAA;IACZ,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACtC,QAAQ,EACR,KAAK,EACL,IAAI,GAKJ;IACA,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAA;IAC1C,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAA;IAE9C,IAAI,SAAS,CAAC,gBAAgB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAEpD,IAAI,mBAAmB,GAAG,cAAc,CAAC,UAAU,CAAA;IAEnD,MAAM,aAAa,GAAG,IAAI,GAAG,CAC5B,mBAAmB,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CACjD,CAAA;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAA;IAEzC,yEAAyE;IACzE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IAC3D,MAAM,iBAAiB,GAAG,MAAM,EAAE,CAAC,QAAQ;SACzC,MAAM,CAAC,eAAe,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;SAC1C,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SAChB,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAA;IAEpB,IAAI,gBAAgB,GAAG;QACtB,GAAG,SAAS,CAAC,gBAAgB;QAC7B,KAAK,EAAE,SAAS,CAAC,gBAAgB,EAAE,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG;KAChE,CAAA;IAED,sFAAsF;IACtF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxB,sDAAsD;QACtD,MAAM,aAAa,GAAG;YACrB,YAAY;YACZ,WAAW;YACX,UAAU;YACV,WAAW;YACX,UAAU;YACV,YAAY;YACZ,WAAW;SACX,CAAA;QAED,IAAI,WAAW,GAAkB,IAAI,CAAA;QACrC,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAC9C,IAAI,CAAC;gBACJ,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBACrD,WAAW,GAAG,QAAQ,CAAA;gBACtB,MAAK;YACN,CAAC;YAAC,MAAM,CAAC;gBACR,SAAQ;YACT,CAAC;QACF,CAAC;QAED,gBAAgB,GAAG;YAClB,GAAG,gBAAgB;YACnB,IAAI,EAAE,QAAQ,EAAE,2CAA2C;YAC3D,YAAY,EAAE,GAAG,EAAE,4BAA4B;YAC/C,cAAc,EAAE,GAAG,EAAE,+BAA+B;YACpD,cAAc,EAAE,GAAG,EAAE,6BAA6B;YAClD,GAAG,CAAC,WAAW,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,4BAA4B;SACvE,CAAA;IACF,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,gBAA0C,CAAC,CAAA;IAE9E,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,eAAe,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAA;IAE5E,MAAM,aAAa,GAAG,IAAI,GAAG,CAC5B,UAAU,UAAU,IAAI,YAAY,IAAI,MAAM,EAAE,EAChD,wBAAwB,CACxB,CAAA;IAED,OAAO,aAAa,CAAC,QAAQ,EAAE,CAAA;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IAClD,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAA;IAE1C,IAAI,cAAc,GAAwB,EAAE,CAAA;IAC5C,IAAI,OAAO,GAA2B,EAAE,CAAA;IAExC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IAC3D,MAAM,iBAAiB,GAAG,MAAM,EAAE,CAAC,QAAQ;SACzC,MAAM,CAAC,eAAe,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;SAC1C,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SAChB,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAA;IAEpB,IAAI,iBAAiB,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACrB,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAChE,CAAA;QACR,cAAc,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAA;QACnC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAA;IAC5B,CAAC;IAED,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;QAChC,gBAAgB,EAAE,sBAAsB,CAAC,QAAQ,EAAE;aACjD,QAAQ,EAAE;aACV,SAAS,CAAC,CAAC,mBAAmB,EAAE,EAAE;YAClC,IAAI,mBAAmB,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAA;YAE7C,OAAO;gBACN,GAAG,cAAc,CAAC,gBAAgB;gBAClC,GAAG,mBAAmB;aACtB,CAAA;QACF,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;aACR,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;iBACR,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC;SAClD,CAAC;aACD,OAAO,CAAC,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;aACR,MAAM,CAAC;YACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC3B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC1B,CAAC;aACD,OAAO,CAAC,EAAE,CAAC;QACb,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC;KACxE,CAAC,CAAA;IAEF,MAAM,SAAS,GAAG;QACjB,gBAAgB,EAAE,cAAc,CAAC,gBAAgB;QACjD,OAAO,EAAE;YACR,OAAO,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO;SACxC;QACD,OAAO,EAAE;YACR,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB;QACD,YAAY,EAAE,cAAc,CAAC,YAAY;KACzC,CAAA;IAED,IAAI,CAAC;QACJ,OAAO,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,EAAE,CAAA;YACvC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC;iBAC/D,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;iBAC3D,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;YACpC,MAAM,IAAI,KAAK,CACd,iCAAiC,QAAQ,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzE,CAAA;QACF,CAAC;QACD,MAAM,KAAK,CAAA;IACZ,CAAC;AACF,CAAC","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { z } from 'zod'\nimport { handleGitHubRepoAndRoot } from './utils.js'\n\nexport const getWorkshopRoot = () =>\n\tprocess.env.EPICSHOP_CONTEXT_CWD ?? process.cwd()\n\nconst getRootPkgJsonPath = () => path.join(getWorkshopRoot(), 'package.json')\n\nexport const StackBlitzConfigSchema = z.object({\n\t// we default this to `${exerciseTitle} (${type})`\n\ttitle: z.string().optional(),\n\t// stackblitz defaults this to dev automatically\n\tstartScript: z.string().optional(),\n\t// if no value is provided, then stackblitz defaults this to whatever\n\t// looks best based on the width of the screen\n\tview: z\n\t\t.union([z.literal('editor'), z.literal('preview'), z.literal('both')])\n\t\t.optional(),\n\tfile: z.string().optional(),\n\thidedevtools: z.string().optional(),\n\tterminalHeight: z.string().optional(),\n\thideNavigation: z.string().optional(),\n})\n\nconst InstructorSchema = z.object({\n\tname: z.string().optional(),\n\tavatar: z.string().optional(),\n\t𝕏: z.string().optional(),\n\txHandle: z.string().optional(),\n})\n\n// most defaults are for backwards compatibility\nconst WorkshopConfigSchema = z\n\t.object({\n\t\ttitle: z.string(),\n\t\tsubtitle: z.string().optional(),\n\t\tinstructor: InstructorSchema.optional(),\n\t\tepicWorkshopHost: z.string().optional(),\n\t\tepicWorkshopSlug: z.string().optional(),\n\t\tsubdomain: z.string().optional(),\n\t\tproduct: z\n\t\t\t.object({\n\t\t\t\thost: z.string().default('www.epicweb.dev'),\n\t\t\t\tdisplayName: z.string().default('EpicWeb.dev'),\n\t\t\t\tdisplayNameShort: z.string().default('Epic Web'),\n\t\t\t\tlogo: z.string().default('/logo.svg'),\n\t\t\t\tslug: z.string().optional(),\n\t\t\t\tdiscordChannelId: z.string().default('1161045224907341972'),\n\t\t\t\tdiscordTags: z.array(z.string()).optional(),\n\t\t\t})\n\t\t\t.default({}),\n\t\tonboardingVideo: z\n\t\t\t.string()\n\t\t\t.default(\n\t\t\t\t'https://www.epicweb.dev/tips/get-started-with-the-epic-workshop-app',\n\t\t\t),\n\t\tgithubRepo: z\n\t\t\t.string()\n\t\t\t.transform((githubRepo) => githubRepo ?? ENV.EPICSHOP_GITHUB_REPO),\n\t\tgithubRoot: z\n\t\t\t.string()\n\t\t\t.transform((githubRoot) => githubRoot ?? ENV.EPICSHOP_GITHUB_ROOT),\n\t\tstackBlitzConfig: StackBlitzConfigSchema.optional(),\n\t\tforms: z\n\t\t\t.object({\n\t\t\t\tworkshop: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.default(\n\t\t\t\t\t\t'https://docs.google.com/forms/d/e/1FAIpQLSdRmj9p8-5zyoqRzxp3UpqSbC3aFkweXvvJIKes0a5s894gzg/viewform?hl=en&embedded=true&entry.2123647600={workshopTitle}',\n\t\t\t\t\t),\n\t\t\t\texercise: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.default(\n\t\t\t\t\t\t'https://docs.google.com/forms/d/e/1FAIpQLSf3o9xyjQepTlOTH5Z7ZwkeSTdXh6YWI_RGc9KiyD3oUN0p6w/viewform?hl=en&embedded=true&entry.1836176234={workshopTitle}&entry.428900931={exerciseTitle}',\n\t\t\t\t\t),\n\t\t\t})\n\t\t\t.default({}),\n\t\ttestTab: z\n\t\t\t.object({\n\t\t\t\tenabled: z.boolean().default(true),\n\t\t\t})\n\t\t\t.default({}),\n\t\tscripts: z\n\t\t\t.object({\n\t\t\t\tpostupdate: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tinitialRoute: z.string().optional().default('/'),\n\t\tnotifications: z\n\t\t\t.array(\n\t\t\t\tz.object({\n\t\t\t\t\tid: z.string(),\n\t\t\t\t\ttitle: z.string(),\n\t\t\t\t\tmessage: z.string(),\n\t\t\t\t\tlink: z.string().optional(),\n\t\t\t\t\ttype: z.enum(['info', 'warning', 'danger']),\n\t\t\t\t\texpiresAt: z.date().nullable(),\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.optional()\n\t\t\t.default([]),\n\t})\n\t.transform((data) => {\n\t\treturn {\n\t\t\t...data,\n\t\t\tproduct: {\n\t\t\t\t...data.product,\n\t\t\t\tdisplayNameShort:\n\t\t\t\t\tdata.product.displayNameShort ?? data.product.displayName,\n\t\t\t\t// for backwards compatibility\n\t\t\t\thost: data.product.host ?? data.epicWorkshopHost,\n\t\t\t\tslug: data.product.slug ?? data.epicWorkshopSlug,\n\t\t\t},\n\t\t}\n\t})\n\nexport type WorkshopConfig = z.infer<typeof WorkshopConfigSchema>\n\nconst configCache: {\n\tconfig: WorkshopConfig | null\n\tmodified: number\n} = {\n\tconfig: null,\n\tmodified: 0,\n}\n\n// Utility to read and parse the root package.json\nfunction readRootPkgJson(): any {\n\tconst packageJsonPath = getRootPkgJsonPath()\n\ttry {\n\t\tconst packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8')\n\t\treturn JSON.parse(packageJsonContent)\n\t} catch (error) {\n\t\tconsole.error(`Error reading or parsing package.json:`, error)\n\t\tif (error instanceof Error && error.message.includes('ENOENT')) {\n\t\t\tthrow new Error(\n\t\t\t\t`package.json not found at ${packageJsonPath}. Please ensure you're running the command from the correct directory.`,\n\t\t\t)\n\t\t} else if (error instanceof SyntaxError) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid JSON in package.json at ${packageJsonPath}. Please check the file for syntax errors.`,\n\t\t\t)\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Could not find and parse package.json at ${packageJsonPath}`,\n\t\t)\n\t}\n}\n\n/**\n * Generate a URL with subdomain support\n * Only applies subdomain logic when not deployed\n */\nexport function getWorkshopUrl(port: number, subdomain?: string): string {\n\t// Check if deployed - use process.env directly since ENV might not be initialized yet\n\tconst isDeployed =\n\t\tprocess.env.EPICSHOP_DEPLOYED === 'true' ||\n\t\tprocess.env.EPICSHOP_DEPLOYED === '1'\n\n\t// Only use subdomain logic when not deployed\n\tif (!isDeployed) {\n\t\tconst config = getWorkshopConfig()\n\t\tlet subdomainToUse = subdomain ?? config.subdomain\n\n\t\t// Fallback to package.json name if subdomain is not set\n\t\tif (!subdomainToUse) {\n\t\t\ttry {\n\t\t\t\tconst packageJson = readRootPkgJson()\n\t\t\t\tif (\n\t\t\t\t\tpackageJson &&\n\t\t\t\t\ttypeof packageJson === 'object' &&\n\t\t\t\t\t'name' in packageJson &&\n\t\t\t\t\ttypeof packageJson.name === 'string'\n\t\t\t\t) {\n\t\t\t\t\tlet name = packageJson.name as string\n\t\t\t\t\t// Sanitize: lowercased, non-alphanumeric to dashes, trim dashes\n\t\t\t\t\tsubdomainToUse = name\n\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t.replace(/[^a-z0-9-]/g, '-')\n\t\t\t\t\t\t.replace(/^-+|-+$/g, '')\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// ignore, fallback to localhost\n\t\t\t}\n\t\t}\n\n\t\tif (subdomainToUse) {\n\t\t\treturn `http://${subdomainToUse}.localhost:${port}`\n\t\t}\n\t}\n\n\treturn `http://localhost:${port}`\n}\n\nexport function getWorkshopConfig(): WorkshopConfig {\n\tif (\n\t\tconfigCache.config &&\n\t\tconfigCache.modified > fs.statSync(getRootPkgJsonPath()).mtimeMs\n\t) {\n\t\treturn configCache.config\n\t}\n\n\tconst packageJson = readRootPkgJson()\n\n\tconst epicshopConfig = packageJson.epicshop || {}\n\n\t// Set githubRepo and githubRoot before parsing\n\tconst { githubRepo, githubRoot } = handleGitHubRepoAndRoot({\n\t\tgithubRepo: epicshopConfig.githubRepo,\n\t\tgithubRoot: epicshopConfig.githubRoot,\n\t})\n\tepicshopConfig.githubRepo = githubRepo\n\tepicshopConfig.githubRoot = githubRoot\n\n\ttry {\n\t\tconst parsedConfig = WorkshopConfigSchema.parse(epicshopConfig)\n\t\tconfigCache.config = parsedConfig\n\t\tconfigCache.modified = fs.statSync(getRootPkgJsonPath()).mtimeMs\n\t\treturn parsedConfig\n\t} catch (error) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tconst flattenedErrors = error.flatten()\n\t\t\tconst errorMessages = Object.entries(flattenedErrors.fieldErrors)\n\t\t\t\t.map(([field, errors]) => `${field}: ${errors?.join(', ')}`)\n\t\t\t\t.concat(flattenedErrors.formErrors)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid epicshop configuration in ${getRootPkgJsonPath()}:\\n${errorMessages.join('\\n')}`,\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n\nexport async function getStackBlitzUrl({\n\tfullPath,\n\ttitle,\n\ttype,\n}: {\n\tfullPath: string\n\ttitle: string\n\ttype: string\n}) {\n\tconst workshopConfig = getWorkshopConfig()\n\tconst appConfig = await getAppConfig(fullPath)\n\n\tif (appConfig.stackBlitzConfig === null) return null\n\n\tlet githubRootUrlString = workshopConfig.githubRoot\n\n\tconst githubRootUrl = new URL(\n\t\tgithubRootUrlString.replace(/\\/blob\\//, '/tree/'),\n\t)\n\n\tconst githubPart = githubRootUrl.pathname\n\n\t// Check if package.json exists to determine if this is a simple exercise\n\tconst packageJsonPath = path.join(fullPath, 'package.json')\n\tconst packageJsonExists = await fs.promises\n\t\t.access(packageJsonPath, fs.constants.F_OK)\n\t\t.then(() => true)\n\t\t.catch(() => false)\n\n\tlet stackBlitzConfig = {\n\t\t...appConfig.stackBlitzConfig,\n\t\ttitle: appConfig.stackBlitzConfig?.title ?? `${title} (${type})`,\n\t}\n\n\t// For simple exercises without package.json, configure StackBlitz to show only editor\n\tif (!packageJsonExists) {\n\t\t// Find the first existing file from the priority list\n\t\tconst priorityFiles = [\n\t\t\t'index.html',\n\t\t\t'index.tsx',\n\t\t\t'index.ts',\n\t\t\t'index.jsx',\n\t\t\t'index.js',\n\t\t\t'README.mdx',\n\t\t\t'README.md',\n\t\t]\n\n\t\tlet defaultFile: string | null = null\n\t\tfor (const fileName of priorityFiles) {\n\t\t\tconst filePath = path.join(fullPath, fileName)\n\t\t\ttry {\n\t\t\t\tawait fs.promises.access(filePath, fs.constants.F_OK)\n\t\t\t\tdefaultFile = fileName\n\t\t\t\tbreak\n\t\t\t} catch {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tstackBlitzConfig = {\n\t\t\t...stackBlitzConfig,\n\t\t\tview: 'editor', // Show only editor, no preview or terminal\n\t\t\thidedevtools: '1', // Hide the console/devtools\n\t\t\tterminalHeight: '0', // Hide the terminal completely\n\t\t\thideNavigation: '1', // Hide the preview's URL bar\n\t\t\t...(defaultFile && { file: defaultFile }), // Set default file if found\n\t\t}\n\t}\n\n\tconst params = new URLSearchParams(stackBlitzConfig as Record<string, string>)\n\n\tconst relativePath = fullPath.replace(`${getWorkshopRoot()}${path.sep}`, '')\n\n\tconst stackBlitzUrl = new URL(\n\t\t`/github${githubPart}/${relativePath}?${params}`,\n\t\t'https://stackblitz.com',\n\t)\n\n\treturn stackBlitzUrl.toString()\n}\n\nexport async function getAppConfig(fullPath: string) {\n\tconst workshopConfig = getWorkshopConfig()\n\n\tlet epicshopConfig: Record<string, any> = {}\n\tlet scripts: Record<string, string> = {}\n\n\tconst packageJsonPath = path.join(fullPath, 'package.json')\n\tconst packageJsonExists = await fs.promises\n\t\t.access(packageJsonPath, fs.constants.F_OK)\n\t\t.then(() => true)\n\t\t.catch(() => false)\n\n\tif (packageJsonExists) {\n\t\tconst pkg = JSON.parse(\n\t\t\tawait fs.promises.readFile(path.join(fullPath, 'package.json'), 'utf8'),\n\t\t) as any\n\t\tepicshopConfig = pkg.epicshop ?? {}\n\t\tscripts = pkg.scripts ?? {}\n\t}\n\n\tconst AppConfigSchema = z.object({\n\t\tstackBlitzConfig: StackBlitzConfigSchema.nullable()\n\t\t\t.optional()\n\t\t\t.transform((appStackBlitzConfig) => {\n\t\t\t\tif (appStackBlitzConfig === null) return null\n\n\t\t\t\treturn {\n\t\t\t\t\t...workshopConfig.stackBlitzConfig,\n\t\t\t\t\t...appStackBlitzConfig,\n\t\t\t\t}\n\t\t\t}),\n\t\ttestTab: z\n\t\t\t.object({\n\t\t\t\tenabled: z\n\t\t\t\t\t.boolean()\n\t\t\t\t\t.optional()\n\t\t\t\t\t.default(workshopConfig.testTab?.enabled ?? true),\n\t\t\t})\n\t\t\t.default({}),\n\t\tscripts: z\n\t\t\t.object({\n\t\t\t\ttest: z.string().optional(),\n\t\t\t\tdev: z.string().optional(),\n\t\t\t})\n\t\t\t.default({}),\n\t\tinitialRoute: z.string().optional().default(workshopConfig.initialRoute),\n\t})\n\n\tconst appConfig = {\n\t\tstackBlitzConfig: epicshopConfig.stackBlitzConfig,\n\t\ttestTab: {\n\t\t\tenabled: epicshopConfig.testTab?.enabled,\n\t\t},\n\t\tscripts: {\n\t\t\ttest: scripts.test,\n\t\t\tdev: scripts.dev,\n\t\t},\n\t\tinitialRoute: epicshopConfig.initialRoute,\n\t}\n\n\ttry {\n\t\treturn AppConfigSchema.parse(appConfig)\n\t} catch (error) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tconst flattenedErrors = error.flatten()\n\t\t\tconst errorMessages = Object.entries(flattenedErrors.fieldErrors)\n\t\t\t\t.map(([field, errors]) => `${field}: ${errors?.join(', ')}`)\n\t\t\t\t.concat(flattenedErrors.formErrors)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid app configuration for ${fullPath}:\\n${errorMessages.join('\\n')}`,\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"diff.server.d.ts","sourceRoot":"","sources":["../../src/diff.server.ts"],"names":[],"mappings":"AAQA,OAAO,EAKN,KAAK,GAAG,EACR,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAA;AA8TjD,wBAAsB,YAAY,CACjC,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EACC,UAAU,EACV,OAAO,EACP,OAAO,GACP,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO;YAwEtB,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS;;;KA1DxG;AAmED,wBAAsB,WAAW,CAChC,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EACC,UAAU,EACV,OAAO,EACP,OAAO,GACP,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,mBActE;AAiHD,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,mBA0BxE"}
1
+ {"version":3,"file":"diff.server.d.ts","sourceRoot":"","sources":["../../src/diff.server.ts"],"names":[],"mappings":"AAQA,OAAO,EAKN,KAAK,GAAG,EACR,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAiUjD,wBAAsB,YAAY,CACjC,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EACC,UAAU,EACV,OAAO,EACP,OAAO,GACP,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO;YAwEtB,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS;;;KA1DxG;AAmED,wBAAsB,WAAW,CAChC,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EACC,UAAU,EACV,OAAO,EACP,OAAO,GACP,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,mBActE;AAiHD,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,mBA0BxE"}
@@ -12,14 +12,17 @@ import { modifiedMoreRecentlyThan } from './modified-time.server.js';
12
12
  const epicshopTempDir = path.join(os.tmpdir(), 'epicshop');
13
13
  const isDeployed = ENV.EPICSHOP_DEPLOYED;
14
14
  const diffTmpDir = path.join(epicshopTempDir, 'diff');
15
+ /**
16
+ * Converts a diff file path to a relative path for display and lookup.
17
+ * - Removes leading/trailing quotes.
18
+ * - Strips diff prefixes like a/, b/, .\a\, .\b\, ./a/, ./b/ (for both POSIX and Windows).
19
+ * - Normalizes the path separators.
20
+ * - Removes the diff temp directory prefix and splits out the actual relative path.
21
+ */
15
22
  function diffPathToRelative(filePath) {
16
- let normalizedPath = path.normalize(filePath.replace(/^("|')|("|')$/g, ''));
17
- if (normalizedPath.startsWith('a\\') ||
18
- normalizedPath.startsWith('b\\') ||
19
- normalizedPath.startsWith('a/') ||
20
- normalizedPath.startsWith('b/')) {
21
- normalizedPath = normalizedPath.slice(2);
22
- }
23
+ let normalizedPath = path.normalize(filePath
24
+ .replace(/^["']|["']$/g, '')
25
+ .replace(/^(\.\\[ab]\\|\.\/[ab]\/|[ab][\\/])/, ''));
23
26
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
27
  const [workshopRootDirname, appId, id, ...relativePath] = normalizedPath
25
28
  .replace(process.platform === 'win32' || normalizedPath.startsWith(path.sep)
@@ -1 +1 @@
1
- {"version":3,"file":"diff.server.js","sourceRoot":"","sources":["../../src/diff.server.ts"],"names":[],"mappings":"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","sourcesContent":["import os from 'os'\nimport path from 'path'\nimport { type CacheEntry } from '@epic-web/cachified'\nimport { execa } from 'execa'\nimport fsExtra from 'fs-extra'\nimport ignore from 'ignore'\nimport parseGitDiff, { type AnyFileChange } from 'parse-git-diff'\nimport { bundledLanguagesInfo } from 'shiki/langs'\nimport {\n\tgetForceFreshForDir,\n\tgetRelativePath,\n\tgetWorkshopRoot,\n\tmodifiedTimes,\n\ttype App,\n} from './apps.server.js'\nimport { cachified, diffCodeCache, diffFilesCache } from './cache.server.js'\nimport { compileMarkdownString } from './compile-mdx.server.js'\nimport { modifiedMoreRecentlyThan } from './modified-time.server.js'\nimport { type Timings } from './timing.server.js'\n\nconst epicshopTempDir = path.join(os.tmpdir(), 'epicshop')\n\nconst isDeployed = ENV.EPICSHOP_DEPLOYED\n\nconst diffTmpDir = path.join(epicshopTempDir, 'diff')\n\nfunction diffPathToRelative(filePath: string) {\n\tlet normalizedPath = path.normalize(filePath.replace(/^(\"|')|(\"|')$/g, ''))\n\tif (\n\t\tnormalizedPath.startsWith('a\\\\') ||\n\t\tnormalizedPath.startsWith('b\\\\') ||\n\t\tnormalizedPath.startsWith('a/') ||\n\t\tnormalizedPath.startsWith('b/')\n\t) {\n\t\tnormalizedPath = normalizedPath.slice(2)\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tconst [workshopRootDirname, appId, id, ...relativePath] = normalizedPath\n\t\t.replace(\n\t\t\tprocess.platform === 'win32' || normalizedPath.startsWith(path.sep)\n\t\t\t\t? `${diffTmpDir}${path.sep}`\n\t\t\t\t: `${diffTmpDir.slice(1)}${path.sep}`,\n\t\t\t'',\n\t\t)\n\t\t.split(path.sep)\n\n\treturn relativePath.join(path.sep)\n}\n\nfunction getLanguage(ext: string) {\n\treturn (\n\t\tbundledLanguagesInfo.find((l) => l.id === ext || l.aliases?.includes(ext))\n\t\t\t?.id ?? 'text'\n\t)\n}\n\nfunction getFileCodeblocks(\n\tfile: ReturnType<typeof parseGitDiff>['files'][number],\n\tfilePathApp1: string,\n\tfilePathApp2: string,\n\ttype: string,\n) {\n\tif (!file.chunks.length) {\n\t\treturn [\n\t\t\t`<p className=\"m-0 p-4 border-b text-muted-foreground\">No changes</p>`,\n\t\t]\n\t}\n\tconst filepath = diffPathToRelative(\n\t\tfile.type === 'RenamedFile' ? file.pathAfter : file.path,\n\t)\n\tconst extension = path.extname(filepath).slice(1)\n\tconst lang = getLanguage(extension)\n\tconst pathToCopy = file.type === 'RenamedFile' ? file.pathBefore : file.path\n\tconst relativePath = diffPathToRelative(pathToCopy)\n\tconst markdownLines = []\n\tfor (const chunk of file.chunks) {\n\t\tconst removedLineNumbers = []\n\t\tconst addedLineNumbers = []\n\t\tconst lines = []\n\t\tlet toStartLine = 0\n\t\tlet startLine = 1\n\t\tif (chunk.type === 'BinaryFilesChunk') {\n\t\t\tlines.push(\n\t\t\t\ttype === 'AddedFile'\n\t\t\t\t\t? `Binary file added`\n\t\t\t\t\t: type === 'DeletedFile'\n\t\t\t\t\t\t? 'Binary file deleted'\n\t\t\t\t\t\t: 'Binary file changed',\n\t\t\t)\n\t\t} else {\n\t\t\tstartLine =\n\t\t\t\tchunk.type === 'Chunk'\n\t\t\t\t\t? chunk.fromFileRange.start\n\t\t\t\t\t: chunk.type === 'CombinedChunk'\n\t\t\t\t\t\t? chunk.fromFileRangeA.start\n\t\t\t\t\t\t: 1\n\t\t\ttoStartLine = chunk.toFileRange.start\n\t\t\tfor (\n\t\t\t\tlet lineNumber = 0;\n\t\t\t\tlineNumber < chunk.changes.length;\n\t\t\t\tlineNumber++\n\t\t\t) {\n\t\t\t\tconst change = chunk.changes[lineNumber]\n\t\t\t\tif (!change) continue\n\t\t\t\tlines.push(change.content)\n\t\t\t\tswitch (change.type) {\n\t\t\t\t\tcase 'AddedLine': {\n\t\t\t\t\t\taddedLineNumbers.push(startLine + lineNumber)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'DeletedLine': {\n\t\t\t\t\t\tremovedLineNumbers.push(startLine + lineNumber)\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}\n\n\t\tconst params = [\n\t\t\t['filename', relativePath.replace(/\\\\/g, '\\\\\\\\')],\n\t\t\t['start', startLine.toString()],\n\t\t\tremovedLineNumbers.length\n\t\t\t\t? ['remove', removedLineNumbers.join(',')]\n\t\t\t\t: null,\n\t\t\taddedLineNumbers.length ? ['add', addedLineNumbers.join(',')] : null,\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.map(([key, value]) => `${key}=${value}`)\n\t\t\t.join(' ')\n\n\t\tconst launchEditorClassName =\n\t\t\t'border hover:bg-foreground/20 rounded px-2 py-0.5 font-mono text-xs font-semibold'\n\n\t\tfunction launchEditor(appNum: number, line: number) {\n\t\t\tif (isDeployed) {\n\t\t\t\tif (type === 'DeletedFile' && appNum === 2) return ''\n\t\t\t\tif (type === 'AddedFile' && appNum === 1) return ''\n\t\t\t}\n\n\t\t\tconst label =\n\t\t\t\t(type === 'AddedFile' && appNum === 1) ||\n\t\t\t\t(type === 'DeletedFile' && appNum === 2)\n\t\t\t\t\t? `CREATE in APP ${appNum}`\n\t\t\t\t\t: `OPEN in APP ${appNum}`\n\t\t\tconst file = JSON.stringify(appNum === 1 ? filePathApp1 : filePathApp2)\n\t\t\tconst fixedTitle = getRelativePath(file)\n\n\t\t\treturn `\n<LaunchEditor file=${file} line={${line}}>\n\t<span title=\"${fixedTitle}\" className=\"${launchEditorClassName}\">${label}</span>\n</LaunchEditor>`\n\t\t}\n\n\t\tmarkdownLines.push(`\n<div className=\"relative\">\n\n\\`\\`\\`${lang} ${params}\n${lines.join('\\n')}\n\\`\\`\\`\n\n<div className=\"flex gap-4 absolute top-1 right-3 items-center\">\n\t${launchEditor(1, startLine)}\n\t<div className=\"display-alt-down flex gap-2\">\n\t\t<LaunchEditor file=${JSON.stringify(\n\t\t\tfilePathApp1,\n\t\t)} syncTo={{file: ${JSON.stringify(filePathApp2)}}}>\n\t\t\t<span className=\"block ${launchEditorClassName}\">\n\t\t\t\t<Icon name=\"ArrowLeft\" title=\"Copy app 2 file to app 1\" />\n\t\t\t</span>\n\t\t</LaunchEditor>\n\t\t<LaunchEditor file=${JSON.stringify(\n\t\t\tfilePathApp2,\n\t\t)} syncTo={{file: ${JSON.stringify(filePathApp1)}}}>\n\t\t\t<span className=\"block ${launchEditorClassName}\">\n\t\t\t\t<Icon name=\"ArrowRight\" title=\"Copy app 1 file to app 2\" />\n\t\t\t</span>\n\t\t</LaunchEditor>\n\t</div>\n\t${launchEditor(2, toStartLine)}\n</div>\n\n</div>\n`)\n\t}\n\treturn markdownLines\n}\n\nconst DEFAULT_IGNORE_PATTERNS = [\n\t'**/README.*',\n\t'**/package-lock.json',\n\t'**/.DS_Store',\n\t'**/.vscode',\n\t'**/.idea',\n\t'**/.git',\n\t'**/*.db',\n\t'**/epicshop/**',\n]\n\nasync function copyUnignoredFiles(\n\tsrcDir: string,\n\tdestDir: string,\n\tignoreList: Array<string>,\n) {\n\tconst key = `COPY_${srcDir}__${destDir}__${ignoreList.join('_')}`\n\tawait cachified({\n\t\tkey,\n\t\tcache: diffCodeCache,\n\t\tforceFresh: getForceFreshForDir(diffCodeCache.get(key), srcDir),\n\t\tasync getFreshValue() {\n\t\t\t// @ts-ignore 🤷‍♂️ weird module stuff\n\t\t\tconst ig = ignore().add(ignoreList)\n\n\t\t\tawait fsExtra.remove(destDir)\n\t\t\tawait fsExtra.copy(srcDir, destDir, {\n\t\t\t\tfilter: async (file) => {\n\t\t\t\t\tif (file === srcDir) return true\n\t\t\t\t\treturn !ig.ignores(path.relative(srcDir, file))\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t})\n}\n\nasync function prepareForDiff(app1: App, app2: App) {\n\tconst id = Math.random().toString(36).slice(2)\n\tconst app1CopyPath = path.join(\n\t\tdiffTmpDir,\n\t\tpath.basename(getWorkshopRoot()),\n\t\tapp1.name,\n\t\tid,\n\t)\n\tconst app2CopyPath = path.join(\n\t\tdiffTmpDir,\n\t\tpath.basename(getWorkshopRoot()),\n\t\tapp2.name,\n\t\tid,\n\t)\n\t// if everything except the `name` property of the `package.json` is the same\n\t// the don't bother copying it\n\tconst comparePkgJson = (pkg1: any, pkg2: any) => {\n\t\tconst { name, ...rest1 } = pkg1\n\t\tconst { name: name2, ...rest2 } = pkg2\n\t\treturn JSON.stringify(rest1) === JSON.stringify(rest2)\n\t}\n\tconst app1PkgJson =\n\t\tapp1.dev.type === 'script'\n\t\t\t? await fsExtra\n\t\t\t\t\t.readJSON(path.join(app1.fullPath, 'package.json'))\n\t\t\t\t\t.catch(() => ({}))\n\t\t\t: {}\n\tconst app2PkgJson =\n\t\tapp1.dev.type === 'script'\n\t\t\t? await fsExtra\n\t\t\t\t\t.readJSON(path.join(app2.fullPath, 'package.json'))\n\t\t\t\t\t.catch(() => ({}))\n\t\t\t: {}\n\tconst pkgJsonIgnore: Array<string> = comparePkgJson(app1PkgJson, app2PkgJson)\n\t\t? ['package.json']\n\t\t: []\n\tconst workshopIgnore = [\n\t\t...(await getDiffIgnore(path.join(getWorkshopRoot(), '.gitignore'))),\n\t\t...(await getDiffIgnore(\n\t\t\tpath.join(getWorkshopRoot(), 'epicshop', '.diffignore'),\n\t\t)),\n\t]\n\n\tawait Promise.all([\n\t\tcopyUnignoredFiles(app1.fullPath, app1CopyPath, [\n\t\t\t...DEFAULT_IGNORE_PATTERNS,\n\t\t\t...pkgJsonIgnore,\n\t\t\t...workshopIgnore,\n\t\t\t...(await getDiffIgnore(path.join(app1.fullPath, '.gitignore'))),\n\t\t\t...(await getDiffIgnore(\n\t\t\t\tpath.join(app1.fullPath, 'epicshop', '.diffignore'),\n\t\t\t)),\n\t\t]),\n\t\tcopyUnignoredFiles(app2.fullPath, app2CopyPath, [\n\t\t\t...DEFAULT_IGNORE_PATTERNS,\n\t\t\t...pkgJsonIgnore,\n\t\t\t...workshopIgnore,\n\t\t\t...(await getDiffIgnore(path.join(app2.fullPath, '.gitignore'))),\n\t\t\t...(await getDiffIgnore(\n\t\t\t\tpath.join(app2.fullPath, 'epicshop', '.diffignore'),\n\t\t\t)),\n\t\t]),\n\t])\n\n\treturn { app1CopyPath, app2CopyPath }\n}\n\nasync function getDiffIgnore(filePath: string): Promise<Array<string>> {\n\treturn (await fsExtra.pathExists(filePath))\n\t\t? fsExtra.readFile(filePath, 'utf8').then((content) =>\n\t\t\t\tcontent\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((line) => line.trim())\n\t\t\t\t\t.filter((line) => !line.startsWith('#'))\n\t\t\t\t\t.filter(Boolean),\n\t\t\t)\n\t\t: []\n}\n\nasync function getForceFreshForDiff(\n\tapp1: App,\n\tapp2: App,\n\tcacheEntry: CacheEntry | null | undefined,\n) {\n\t// don't know when the cache was created? force refresh\n\tconst cacheModified = cacheEntry?.metadata.createdTime\n\tif (!cacheModified) return true\n\n\t// app1 modified after cache? force refresh\n\tconst app1Modified = modifiedTimes.get(app1.fullPath) ?? 0\n\tif (app1Modified > cacheModified) return true\n\n\t// app2 modified after cache? force refresh\n\tconst app2Modified = modifiedTimes.get(app2.fullPath) ?? 0\n\tif (app2Modified > cacheModified) return true\n\n\t// ok, now let's actually check the modified times of all files in the\n\t// directories and as soon as we find a file that was modified more recently\n\t// then we know we need to force refresh\n\tconst modifiedMoreRecently = await modifiedMoreRecentlyThan(\n\t\tcacheModified,\n\t\tapp1.fullPath,\n\t\tapp2.fullPath,\n\t)\n\tif (modifiedMoreRecently) return true\n\n\treturn undefined\n}\n\nexport async function getDiffFiles(\n\tapp1: App,\n\tapp2: App,\n\t{\n\t\tforceFresh,\n\t\ttimings,\n\t\trequest,\n\t}: { forceFresh?: boolean; timings?: Timings; request?: Request } = {},\n) {\n\tconst key = `${app1.relativePath}__vs__${app2.relativePath}`\n\tconst cacheEntry = diffFilesCache.get(key)\n\tconst result = await cachified({\n\t\tkey,\n\t\tcache: diffFilesCache,\n\t\tforceFresh:\n\t\t\tforceFresh || (await getForceFreshForDiff(app1, app2, cacheEntry)),\n\t\ttimings,\n\t\trequest,\n\t\tgetFreshValue: () => getDiffFilesImpl(app1, app2),\n\t})\n\treturn result\n}\n\nfunction getAppTestFiles(app: App) {\n\treturn app.test.type === 'browser' ? app.test.testFiles : []\n}\n\nasync function getDiffFilesImpl(app1: App, app2: App) {\n\tif (app1.name === app2.name) {\n\t\treturn []\n\t}\n\tconst { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2)\n\n\tconst { stdout: diffOutput } = await execa(\n\t\t'git',\n\t\t[\n\t\t\t'diff',\n\t\t\t'--no-index',\n\t\t\t'--ignore-blank-lines',\n\t\t\t'--ignore-space-change',\n\t\t\tapp1CopyPath,\n\t\t\tapp2CopyPath,\n\t\t],\n\t\t{ cwd: diffTmpDir },\n\t\t// --no-index implies --exit-code, so we need to use the error output\n\t).catch((e) => e as { stdout: string })\n\n\tvoid fsExtra.remove(app1CopyPath)\n\tvoid fsExtra.remove(app2CopyPath)\n\n\tconst typesMap = {\n\t\tChangedFile: 'modified',\n\t\tAddedFile: 'added',\n\t\tDeletedFile: 'deleted',\n\t\tRenamedFile: 'renamed',\n\t}\n\n\tconst parsed = parseGitDiff(diffOutput, { noPrefix: true })\n\n\tconst testFiles = Array.from(\n\t\tnew Set([...getAppTestFiles(app1), ...getAppTestFiles(app2)]),\n\t)\n\n\tconst startLine = (file: AnyFileChange) => {\n\t\tconst chunk = file.type === 'ChangedFile' && file.chunks[0]\n\t\tif (chunk) {\n\t\t\treturn chunk.type === 'Chunk'\n\t\t\t\t? chunk.fromFileRange.start\n\t\t\t\t: chunk.type === 'CombinedChunk'\n\t\t\t\t\t? chunk.fromFileRangeA.start\n\t\t\t\t\t: 1\n\t\t}\n\t\treturn 1\n\t}\n\n\treturn parsed.files\n\t\t.map((file) => ({\n\t\t\t// prettier-ignore\n\n\t\t\tstatus: (typesMap[file.type] ?? 'unknown') as 'renamed' | 'modified' | 'deleted' | 'added' | 'unknown',\n\t\t\tpath: diffPathToRelative(\n\t\t\t\tfile.type === 'RenamedFile' ? file.pathBefore : file.path,\n\t\t\t),\n\t\t\tline: startLine(file),\n\t\t}))\n\t\t.filter((file) => !testFiles.includes(file.path))\n}\n\nexport async function getDiffCode(\n\tapp1: App,\n\tapp2: App,\n\t{\n\t\tforceFresh,\n\t\ttimings,\n\t\trequest,\n\t}: { forceFresh?: boolean; timings?: Timings; request?: Request } = {},\n) {\n\tconst key = `${app1.relativePath}__vs__${app2.relativePath}`\n\tconst cacheEntry = diffCodeCache.get(key)\n\tconst result = await cachified({\n\t\tkey,\n\t\tcache: diffCodeCache,\n\t\tforceFresh:\n\t\t\tforceFresh || (await getForceFreshForDiff(app1, app2, cacheEntry)),\n\t\ttimings,\n\t\trequest,\n\t\tgetFreshValue: () => getDiffCodeImpl(app1, app2),\n\t})\n\treturn result\n}\n\nasync function getDiffCodeImpl(app1: App, app2: App) {\n\tconst markdownLines = ['']\n\n\tif (app1.name === app2.name) {\n\t\tmarkdownLines.push(\n\t\t\t'<p className=\"p-4 text-center\">You are comparing the same app</p>',\n\t\t)\n\t\tconst code = await compileMarkdownString(markdownLines.join('\\n'))\n\t\treturn code\n\t}\n\n\tconst { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2)\n\n\tconst { stdout: diffOutput } = await execa(\n\t\t'git',\n\t\t[\n\t\t\t'diff',\n\t\t\t'--no-index',\n\t\t\tapp1CopyPath,\n\t\t\tapp2CopyPath,\n\t\t\t'--color=never',\n\t\t\t'--color-moved-ws=allow-indentation-change',\n\t\t\t'--no-prefix',\n\t\t\t'--ignore-blank-lines',\n\t\t\t'--ignore-space-change',\n\t\t],\n\t\t{ cwd: diffTmpDir },\n\t\t// --no-index implies --exit-code, so we need to use the error output\n\t).catch((e) => e as { stdout: string })\n\n\tvoid fsExtra.remove(app1CopyPath)\n\tvoid fsExtra.remove(app2CopyPath)\n\n\tconst parsed = parseGitDiff(diffOutput)\n\n\tif (!parsed.files.length) {\n\t\tmarkdownLines.push(\n\t\t\t'<div className=\"m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background\">No changes</div>',\n\t\t)\n\t}\n\n\tconst app1TestFiles = getAppTestFiles(app1)\n\tconst app2TestFiles = getAppTestFiles(app2)\n\n\tfor (const file of parsed.files) {\n\t\tconst pathToCopy = file.type === 'RenamedFile' ? file.pathBefore : file.path\n\t\tconst relativePath = diffPathToRelative(pathToCopy)\n\t\tif (app1TestFiles.includes(relativePath)) continue\n\t\tconst filePathApp1 = path.join(app1.fullPath, relativePath)\n\n\t\tconst pathToApp2 = file.type === 'RenamedFile' ? file.pathAfter : file.path\n\t\tconst relativePathApp2 = diffPathToRelative(pathToApp2)\n\t\tif (app2TestFiles.includes(relativePathApp2)) continue\n\t\tconst filePathApp2 = path.join(app2.fullPath, relativePathApp2)\n\n\t\tswitch (file.type) {\n\t\t\tcase 'ChangedFile': {\n\t\t\t\tmarkdownLines.push(`\n\n<Accordion title=${JSON.stringify(relativePath)} variant=\"changed\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'DeletedFile': {\n\t\t\t\tmarkdownLines.push(`\n<Accordion title=${JSON.stringify(relativePath)} variant=\"deleted\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'RenamedFile': {\n\t\t\t\tconst relativeBefore = diffPathToRelative(file.pathBefore)\n\t\t\t\tconst relativeAfter = diffPathToRelative(file.pathAfter)\n\t\t\t\tconst title = JSON.stringify(`${relativeBefore} ▶️ ${relativeAfter}`)\n\t\t\t\tmarkdownLines.push(`\n<Accordion title=${title} variant=\"renamed\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'AddedFile': {\n\t\t\t\tmarkdownLines.push(`\n<Accordion title=${JSON.stringify(relativePath)} variant=\"added\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconsole.error(file)\n\t\t\t\tthrow new Error(`Unknown file type: ${file}`)\n\t\t\t}\n\t\t}\n\t}\n\tconst code = await compileMarkdownString(markdownLines.join('\\n'))\n\treturn code\n}\n\nexport async function getDiffOutputWithRelativePaths(app1: App, app2: App) {\n\tconst { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2)\n\n\tconst { stdout: diffOutput } = await execa(\n\t\t'git',\n\t\t[\n\t\t\t'diff',\n\t\t\t'--no-index',\n\t\t\tapp1CopyPath,\n\t\t\tapp2CopyPath,\n\t\t\t'--color=never',\n\t\t\t'--color-moved-ws=allow-indentation-change',\n\t\t\t'--no-prefix',\n\t\t\t'--ignore-blank-lines',\n\t\t\t'--ignore-space-change',\n\t\t],\n\t\t{ cwd: diffTmpDir },\n\t\t// --no-index implies --exit-code, so we need to use the error output\n\t).catch((e) => e as { stdout: string })\n\n\tvoid fsExtra.remove(app1CopyPath)\n\tvoid fsExtra.remove(app2CopyPath)\n\n\treturn diffOutput\n\t\t.replaceAll(app1CopyPath.slice(1), '.')\n\t\t.replaceAll(app2CopyPath.slice(1), '.')\n}\n"]}
1
+ {"version":3,"file":"diff.server.js","sourceRoot":"","sources":["../../src/diff.server.ts"],"names":[],"mappings":"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","sourcesContent":["import os from 'os'\nimport path from 'path'\nimport { type CacheEntry } from '@epic-web/cachified'\nimport { execa } from 'execa'\nimport fsExtra from 'fs-extra'\nimport ignore from 'ignore'\nimport parseGitDiff, { type AnyFileChange } from 'parse-git-diff'\nimport { bundledLanguagesInfo } from 'shiki/langs'\nimport {\n\tgetForceFreshForDir,\n\tgetRelativePath,\n\tgetWorkshopRoot,\n\tmodifiedTimes,\n\ttype App,\n} from './apps.server.js'\nimport { cachified, diffCodeCache, diffFilesCache } from './cache.server.js'\nimport { compileMarkdownString } from './compile-mdx.server.js'\nimport { modifiedMoreRecentlyThan } from './modified-time.server.js'\nimport { type Timings } from './timing.server.js'\n\nconst epicshopTempDir = path.join(os.tmpdir(), 'epicshop')\n\nconst isDeployed = ENV.EPICSHOP_DEPLOYED\n\nconst diffTmpDir = path.join(epicshopTempDir, 'diff')\n\n/**\n * Converts a diff file path to a relative path for display and lookup.\n * - Removes leading/trailing quotes.\n * - Strips diff prefixes like a/, b/, .\\a\\, .\\b\\, ./a/, ./b/ (for both POSIX and Windows).\n * - Normalizes the path separators.\n * - Removes the diff temp directory prefix and splits out the actual relative path.\n */\nfunction diffPathToRelative(filePath: string) {\n\tlet normalizedPath = path.normalize(\n\t\tfilePath\n\t\t\t.replace(/^[\"']|[\"']$/g, '')\n\t\t\t.replace(/^(\\.\\\\[ab]\\\\|\\.\\/[ab]\\/|[ab][\\\\/])/, ''),\n\t)\n\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tconst [workshopRootDirname, appId, id, ...relativePath] = normalizedPath\n\t\t.replace(\n\t\t\tprocess.platform === 'win32' || normalizedPath.startsWith(path.sep)\n\t\t\t\t? `${diffTmpDir}${path.sep}`\n\t\t\t\t: `${diffTmpDir.slice(1)}${path.sep}`,\n\t\t\t'',\n\t\t)\n\t\t.split(path.sep)\n\n\treturn relativePath.join(path.sep)\n}\n\nfunction getLanguage(ext: string) {\n\treturn (\n\t\tbundledLanguagesInfo.find((l) => l.id === ext || l.aliases?.includes(ext))\n\t\t\t?.id ?? 'text'\n\t)\n}\n\nfunction getFileCodeblocks(\n\tfile: ReturnType<typeof parseGitDiff>['files'][number],\n\tfilePathApp1: string,\n\tfilePathApp2: string,\n\ttype: string,\n) {\n\tif (!file.chunks.length) {\n\t\treturn [\n\t\t\t`<p className=\"m-0 p-4 border-b text-muted-foreground\">No changes</p>`,\n\t\t]\n\t}\n\tconst filepath = diffPathToRelative(\n\t\tfile.type === 'RenamedFile' ? file.pathAfter : file.path,\n\t)\n\tconst extension = path.extname(filepath).slice(1)\n\tconst lang = getLanguage(extension)\n\tconst pathToCopy = file.type === 'RenamedFile' ? file.pathBefore : file.path\n\tconst relativePath = diffPathToRelative(pathToCopy)\n\tconst markdownLines = []\n\tfor (const chunk of file.chunks) {\n\t\tconst removedLineNumbers = []\n\t\tconst addedLineNumbers = []\n\t\tconst lines = []\n\t\tlet toStartLine = 0\n\t\tlet startLine = 1\n\t\tif (chunk.type === 'BinaryFilesChunk') {\n\t\t\tlines.push(\n\t\t\t\ttype === 'AddedFile'\n\t\t\t\t\t? `Binary file added`\n\t\t\t\t\t: type === 'DeletedFile'\n\t\t\t\t\t\t? 'Binary file deleted'\n\t\t\t\t\t\t: 'Binary file changed',\n\t\t\t)\n\t\t} else {\n\t\t\tstartLine =\n\t\t\t\tchunk.type === 'Chunk'\n\t\t\t\t\t? chunk.fromFileRange.start\n\t\t\t\t\t: chunk.type === 'CombinedChunk'\n\t\t\t\t\t\t? chunk.fromFileRangeA.start\n\t\t\t\t\t\t: 1\n\t\t\ttoStartLine = chunk.toFileRange.start\n\t\t\tfor (\n\t\t\t\tlet lineNumber = 0;\n\t\t\t\tlineNumber < chunk.changes.length;\n\t\t\t\tlineNumber++\n\t\t\t) {\n\t\t\t\tconst change = chunk.changes[lineNumber]\n\t\t\t\tif (!change) continue\n\t\t\t\tlines.push(change.content)\n\t\t\t\tswitch (change.type) {\n\t\t\t\t\tcase 'AddedLine': {\n\t\t\t\t\t\taddedLineNumbers.push(startLine + lineNumber)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'DeletedLine': {\n\t\t\t\t\t\tremovedLineNumbers.push(startLine + lineNumber)\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}\n\n\t\tconst params = [\n\t\t\t['filename', relativePath.replace(/\\\\/g, '\\\\\\\\')],\n\t\t\t['start', startLine.toString()],\n\t\t\tremovedLineNumbers.length\n\t\t\t\t? ['remove', removedLineNumbers.join(',')]\n\t\t\t\t: null,\n\t\t\taddedLineNumbers.length ? ['add', addedLineNumbers.join(',')] : null,\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.map(([key, value]) => `${key}=${value}`)\n\t\t\t.join(' ')\n\n\t\tconst launchEditorClassName =\n\t\t\t'border hover:bg-foreground/20 rounded px-2 py-0.5 font-mono text-xs font-semibold'\n\n\t\tfunction launchEditor(appNum: number, line: number) {\n\t\t\tif (isDeployed) {\n\t\t\t\tif (type === 'DeletedFile' && appNum === 2) return ''\n\t\t\t\tif (type === 'AddedFile' && appNum === 1) return ''\n\t\t\t}\n\n\t\t\tconst label =\n\t\t\t\t(type === 'AddedFile' && appNum === 1) ||\n\t\t\t\t(type === 'DeletedFile' && appNum === 2)\n\t\t\t\t\t? `CREATE in APP ${appNum}`\n\t\t\t\t\t: `OPEN in APP ${appNum}`\n\t\t\tconst file = JSON.stringify(appNum === 1 ? filePathApp1 : filePathApp2)\n\t\t\tconst fixedTitle = getRelativePath(file)\n\n\t\t\treturn `\n<LaunchEditor file=${file} line={${line}}>\n\t<span title=\"${fixedTitle}\" className=\"${launchEditorClassName}\">${label}</span>\n</LaunchEditor>`\n\t\t}\n\n\t\tmarkdownLines.push(`\n<div className=\"relative\">\n\n\\`\\`\\`${lang} ${params}\n${lines.join('\\n')}\n\\`\\`\\`\n\n<div className=\"flex gap-4 absolute top-1 right-3 items-center\">\n\t${launchEditor(1, startLine)}\n\t<div className=\"display-alt-down flex gap-2\">\n\t\t<LaunchEditor file=${JSON.stringify(\n\t\t\tfilePathApp1,\n\t\t)} syncTo={{file: ${JSON.stringify(filePathApp2)}}}>\n\t\t\t<span className=\"block ${launchEditorClassName}\">\n\t\t\t\t<Icon name=\"ArrowLeft\" title=\"Copy app 2 file to app 1\" />\n\t\t\t</span>\n\t\t</LaunchEditor>\n\t\t<LaunchEditor file=${JSON.stringify(\n\t\t\tfilePathApp2,\n\t\t)} syncTo={{file: ${JSON.stringify(filePathApp1)}}}>\n\t\t\t<span className=\"block ${launchEditorClassName}\">\n\t\t\t\t<Icon name=\"ArrowRight\" title=\"Copy app 1 file to app 2\" />\n\t\t\t</span>\n\t\t</LaunchEditor>\n\t</div>\n\t${launchEditor(2, toStartLine)}\n</div>\n\n</div>\n`)\n\t}\n\treturn markdownLines\n}\n\nconst DEFAULT_IGNORE_PATTERNS = [\n\t'**/README.*',\n\t'**/package-lock.json',\n\t'**/.DS_Store',\n\t'**/.vscode',\n\t'**/.idea',\n\t'**/.git',\n\t'**/*.db',\n\t'**/epicshop/**',\n]\n\nasync function copyUnignoredFiles(\n\tsrcDir: string,\n\tdestDir: string,\n\tignoreList: Array<string>,\n) {\n\tconst key = `COPY_${srcDir}__${destDir}__${ignoreList.join('_')}`\n\tawait cachified({\n\t\tkey,\n\t\tcache: diffCodeCache,\n\t\tforceFresh: getForceFreshForDir(diffCodeCache.get(key), srcDir),\n\t\tasync getFreshValue() {\n\t\t\t// @ts-ignore 🤷‍♂️ weird module stuff\n\t\t\tconst ig = ignore().add(ignoreList)\n\n\t\t\tawait fsExtra.remove(destDir)\n\t\t\tawait fsExtra.copy(srcDir, destDir, {\n\t\t\t\tfilter: async (file) => {\n\t\t\t\t\tif (file === srcDir) return true\n\t\t\t\t\treturn !ig.ignores(path.relative(srcDir, file))\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t})\n}\n\nasync function prepareForDiff(app1: App, app2: App) {\n\tconst id = Math.random().toString(36).slice(2)\n\tconst app1CopyPath = path.join(\n\t\tdiffTmpDir,\n\t\tpath.basename(getWorkshopRoot()),\n\t\tapp1.name,\n\t\tid,\n\t)\n\tconst app2CopyPath = path.join(\n\t\tdiffTmpDir,\n\t\tpath.basename(getWorkshopRoot()),\n\t\tapp2.name,\n\t\tid,\n\t)\n\t// if everything except the `name` property of the `package.json` is the same\n\t// the don't bother copying it\n\tconst comparePkgJson = (pkg1: any, pkg2: any) => {\n\t\tconst { name, ...rest1 } = pkg1\n\t\tconst { name: name2, ...rest2 } = pkg2\n\t\treturn JSON.stringify(rest1) === JSON.stringify(rest2)\n\t}\n\tconst app1PkgJson =\n\t\tapp1.dev.type === 'script'\n\t\t\t? await fsExtra\n\t\t\t\t\t.readJSON(path.join(app1.fullPath, 'package.json'))\n\t\t\t\t\t.catch(() => ({}))\n\t\t\t: {}\n\tconst app2PkgJson =\n\t\tapp1.dev.type === 'script'\n\t\t\t? await fsExtra\n\t\t\t\t\t.readJSON(path.join(app2.fullPath, 'package.json'))\n\t\t\t\t\t.catch(() => ({}))\n\t\t\t: {}\n\tconst pkgJsonIgnore: Array<string> = comparePkgJson(app1PkgJson, app2PkgJson)\n\t\t? ['package.json']\n\t\t: []\n\tconst workshopIgnore = [\n\t\t...(await getDiffIgnore(path.join(getWorkshopRoot(), '.gitignore'))),\n\t\t...(await getDiffIgnore(\n\t\t\tpath.join(getWorkshopRoot(), 'epicshop', '.diffignore'),\n\t\t)),\n\t]\n\n\tawait Promise.all([\n\t\tcopyUnignoredFiles(app1.fullPath, app1CopyPath, [\n\t\t\t...DEFAULT_IGNORE_PATTERNS,\n\t\t\t...pkgJsonIgnore,\n\t\t\t...workshopIgnore,\n\t\t\t...(await getDiffIgnore(path.join(app1.fullPath, '.gitignore'))),\n\t\t\t...(await getDiffIgnore(\n\t\t\t\tpath.join(app1.fullPath, 'epicshop', '.diffignore'),\n\t\t\t)),\n\t\t]),\n\t\tcopyUnignoredFiles(app2.fullPath, app2CopyPath, [\n\t\t\t...DEFAULT_IGNORE_PATTERNS,\n\t\t\t...pkgJsonIgnore,\n\t\t\t...workshopIgnore,\n\t\t\t...(await getDiffIgnore(path.join(app2.fullPath, '.gitignore'))),\n\t\t\t...(await getDiffIgnore(\n\t\t\t\tpath.join(app2.fullPath, 'epicshop', '.diffignore'),\n\t\t\t)),\n\t\t]),\n\t])\n\n\treturn { app1CopyPath, app2CopyPath }\n}\n\nasync function getDiffIgnore(filePath: string): Promise<Array<string>> {\n\treturn (await fsExtra.pathExists(filePath))\n\t\t? fsExtra.readFile(filePath, 'utf8').then((content) =>\n\t\t\t\tcontent\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((line) => line.trim())\n\t\t\t\t\t.filter((line) => !line.startsWith('#'))\n\t\t\t\t\t.filter(Boolean),\n\t\t\t)\n\t\t: []\n}\n\nasync function getForceFreshForDiff(\n\tapp1: App,\n\tapp2: App,\n\tcacheEntry: CacheEntry | null | undefined,\n) {\n\t// don't know when the cache was created? force refresh\n\tconst cacheModified = cacheEntry?.metadata.createdTime\n\tif (!cacheModified) return true\n\n\t// app1 modified after cache? force refresh\n\tconst app1Modified = modifiedTimes.get(app1.fullPath) ?? 0\n\tif (app1Modified > cacheModified) return true\n\n\t// app2 modified after cache? force refresh\n\tconst app2Modified = modifiedTimes.get(app2.fullPath) ?? 0\n\tif (app2Modified > cacheModified) return true\n\n\t// ok, now let's actually check the modified times of all files in the\n\t// directories and as soon as we find a file that was modified more recently\n\t// then we know we need to force refresh\n\tconst modifiedMoreRecently = await modifiedMoreRecentlyThan(\n\t\tcacheModified,\n\t\tapp1.fullPath,\n\t\tapp2.fullPath,\n\t)\n\tif (modifiedMoreRecently) return true\n\n\treturn undefined\n}\n\nexport async function getDiffFiles(\n\tapp1: App,\n\tapp2: App,\n\t{\n\t\tforceFresh,\n\t\ttimings,\n\t\trequest,\n\t}: { forceFresh?: boolean; timings?: Timings; request?: Request } = {},\n) {\n\tconst key = `${app1.relativePath}__vs__${app2.relativePath}`\n\tconst cacheEntry = diffFilesCache.get(key)\n\tconst result = await cachified({\n\t\tkey,\n\t\tcache: diffFilesCache,\n\t\tforceFresh:\n\t\t\tforceFresh || (await getForceFreshForDiff(app1, app2, cacheEntry)),\n\t\ttimings,\n\t\trequest,\n\t\tgetFreshValue: () => getDiffFilesImpl(app1, app2),\n\t})\n\treturn result\n}\n\nfunction getAppTestFiles(app: App) {\n\treturn app.test.type === 'browser' ? app.test.testFiles : []\n}\n\nasync function getDiffFilesImpl(app1: App, app2: App) {\n\tif (app1.name === app2.name) {\n\t\treturn []\n\t}\n\tconst { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2)\n\n\tconst { stdout: diffOutput } = await execa(\n\t\t'git',\n\t\t[\n\t\t\t'diff',\n\t\t\t'--no-index',\n\t\t\t'--ignore-blank-lines',\n\t\t\t'--ignore-space-change',\n\t\t\tapp1CopyPath,\n\t\t\tapp2CopyPath,\n\t\t],\n\t\t{ cwd: diffTmpDir },\n\t\t// --no-index implies --exit-code, so we need to use the error output\n\t).catch((e) => e as { stdout: string })\n\n\tvoid fsExtra.remove(app1CopyPath)\n\tvoid fsExtra.remove(app2CopyPath)\n\n\tconst typesMap = {\n\t\tChangedFile: 'modified',\n\t\tAddedFile: 'added',\n\t\tDeletedFile: 'deleted',\n\t\tRenamedFile: 'renamed',\n\t}\n\n\tconst parsed = parseGitDiff(diffOutput, { noPrefix: true })\n\n\tconst testFiles = Array.from(\n\t\tnew Set([...getAppTestFiles(app1), ...getAppTestFiles(app2)]),\n\t)\n\n\tconst startLine = (file: AnyFileChange) => {\n\t\tconst chunk = file.type === 'ChangedFile' && file.chunks[0]\n\t\tif (chunk) {\n\t\t\treturn chunk.type === 'Chunk'\n\t\t\t\t? chunk.fromFileRange.start\n\t\t\t\t: chunk.type === 'CombinedChunk'\n\t\t\t\t\t? chunk.fromFileRangeA.start\n\t\t\t\t\t: 1\n\t\t}\n\t\treturn 1\n\t}\n\n\treturn parsed.files\n\t\t.map((file) => ({\n\t\t\t// prettier-ignore\n\n\t\t\tstatus: (typesMap[file.type] ?? 'unknown') as 'renamed' | 'modified' | 'deleted' | 'added' | 'unknown',\n\t\t\tpath: diffPathToRelative(\n\t\t\t\tfile.type === 'RenamedFile' ? file.pathBefore : file.path,\n\t\t\t),\n\t\t\tline: startLine(file),\n\t\t}))\n\t\t.filter((file) => !testFiles.includes(file.path))\n}\n\nexport async function getDiffCode(\n\tapp1: App,\n\tapp2: App,\n\t{\n\t\tforceFresh,\n\t\ttimings,\n\t\trequest,\n\t}: { forceFresh?: boolean; timings?: Timings; request?: Request } = {},\n) {\n\tconst key = `${app1.relativePath}__vs__${app2.relativePath}`\n\tconst cacheEntry = diffCodeCache.get(key)\n\tconst result = await cachified({\n\t\tkey,\n\t\tcache: diffCodeCache,\n\t\tforceFresh:\n\t\t\tforceFresh || (await getForceFreshForDiff(app1, app2, cacheEntry)),\n\t\ttimings,\n\t\trequest,\n\t\tgetFreshValue: () => getDiffCodeImpl(app1, app2),\n\t})\n\treturn result\n}\n\nasync function getDiffCodeImpl(app1: App, app2: App) {\n\tconst markdownLines = ['']\n\n\tif (app1.name === app2.name) {\n\t\tmarkdownLines.push(\n\t\t\t'<p className=\"p-4 text-center\">You are comparing the same app</p>',\n\t\t)\n\t\tconst code = await compileMarkdownString(markdownLines.join('\\n'))\n\t\treturn code\n\t}\n\n\tconst { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2)\n\n\tconst { stdout: diffOutput } = await execa(\n\t\t'git',\n\t\t[\n\t\t\t'diff',\n\t\t\t'--no-index',\n\t\t\tapp1CopyPath,\n\t\t\tapp2CopyPath,\n\t\t\t'--color=never',\n\t\t\t'--color-moved-ws=allow-indentation-change',\n\t\t\t'--no-prefix',\n\t\t\t'--ignore-blank-lines',\n\t\t\t'--ignore-space-change',\n\t\t],\n\t\t{ cwd: diffTmpDir },\n\t\t// --no-index implies --exit-code, so we need to use the error output\n\t).catch((e) => e as { stdout: string })\n\n\tvoid fsExtra.remove(app1CopyPath)\n\tvoid fsExtra.remove(app2CopyPath)\n\n\tconst parsed = parseGitDiff(diffOutput)\n\n\tif (!parsed.files.length) {\n\t\tmarkdownLines.push(\n\t\t\t'<div className=\"m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background\">No changes</div>',\n\t\t)\n\t}\n\n\tconst app1TestFiles = getAppTestFiles(app1)\n\tconst app2TestFiles = getAppTestFiles(app2)\n\n\tfor (const file of parsed.files) {\n\t\tconst pathToCopy = file.type === 'RenamedFile' ? file.pathBefore : file.path\n\t\tconst relativePath = diffPathToRelative(pathToCopy)\n\t\tif (app1TestFiles.includes(relativePath)) continue\n\t\tconst filePathApp1 = path.join(app1.fullPath, relativePath)\n\n\t\tconst pathToApp2 = file.type === 'RenamedFile' ? file.pathAfter : file.path\n\t\tconst relativePathApp2 = diffPathToRelative(pathToApp2)\n\t\tif (app2TestFiles.includes(relativePathApp2)) continue\n\t\tconst filePathApp2 = path.join(app2.fullPath, relativePathApp2)\n\n\t\tswitch (file.type) {\n\t\t\tcase 'ChangedFile': {\n\t\t\t\tmarkdownLines.push(`\n\n<Accordion title=${JSON.stringify(relativePath)} variant=\"changed\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'DeletedFile': {\n\t\t\t\tmarkdownLines.push(`\n<Accordion title=${JSON.stringify(relativePath)} variant=\"deleted\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'RenamedFile': {\n\t\t\t\tconst relativeBefore = diffPathToRelative(file.pathBefore)\n\t\t\t\tconst relativeAfter = diffPathToRelative(file.pathAfter)\n\t\t\t\tconst title = JSON.stringify(`${relativeBefore} ▶️ ${relativeAfter}`)\n\t\t\t\tmarkdownLines.push(`\n<Accordion title=${title} variant=\"renamed\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'AddedFile': {\n\t\t\t\tmarkdownLines.push(`\n<Accordion title=${JSON.stringify(relativePath)} variant=\"added\">\n\n${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join('\\n')}\n\n</Accordion>\n`)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconsole.error(file)\n\t\t\t\tthrow new Error(`Unknown file type: ${file}`)\n\t\t\t}\n\t\t}\n\t}\n\tconst code = await compileMarkdownString(markdownLines.join('\\n'))\n\treturn code\n}\n\nexport async function getDiffOutputWithRelativePaths(app1: App, app2: App) {\n\tconst { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2)\n\n\tconst { stdout: diffOutput } = await execa(\n\t\t'git',\n\t\t[\n\t\t\t'diff',\n\t\t\t'--no-index',\n\t\t\tapp1CopyPath,\n\t\t\tapp2CopyPath,\n\t\t\t'--color=never',\n\t\t\t'--color-moved-ws=allow-indentation-change',\n\t\t\t'--no-prefix',\n\t\t\t'--ignore-blank-lines',\n\t\t\t'--ignore-space-change',\n\t\t],\n\t\t{ cwd: diffTmpDir },\n\t\t// --no-index implies --exit-code, so we need to use the error output\n\t).catch((e) => e as { stdout: string })\n\n\tvoid fsExtra.remove(app1CopyPath)\n\tvoid fsExtra.remove(app2CopyPath)\n\n\treturn diffOutput\n\t\t.replaceAll(app1CopyPath.slice(1), '.')\n\t\t.replaceAll(app2CopyPath.slice(1), '.')\n}\n"]}
@@ -162,7 +162,7 @@ export async function waitOnApp(app) {
162
162
  let lastError;
163
163
  while (Date.now() - startTime < timeout) {
164
164
  try {
165
- const url = await getWorkshopUrl(app.dev.portNumber);
165
+ const url = getWorkshopUrl(app.dev.portNumber);
166
166
  await fetch(url, {
167
167
  method: 'HEAD',
168
168
  headers: { Accept: '*/*' },
@@ -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 { spawn, type ChildProcess } from 'child_process'\nimport net from 'node:net'\nimport { remember } from '@epic-web/remember'\nimport chalk from 'chalk'\nimport closeWithGrace from 'close-with-grace'\nimport findProcess from 'find-process'\nimport fkill from 'fkill'\nimport { type App } from './apps.server.js'\nimport { getWorkshopUrl } from './config.server.js'\nimport { 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', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: String(portNumber),\n\t\t\tAPP_SERVER_PORT: String(portNumber),\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst prefix = chalk[color](\n\t\t`[${app.name.replace(/^exercises\\./, '')}:${portNumber}]`,\n\t)\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stderr.on('data', handleStdErrData)\n\tdevProcesses.set(key, { color, process: appProcess, port: portNumber })\n\tappProcess.on('exit', (code) => {\n\t\tappProcess.stdout.off('data', handleStdOutData)\n\t\tappProcess.stderr.off('data', handleStdErrData)\n\t\tconsole.log(`${prefix} exited (${code})`)\n\t\tdevProcesses.delete(key)\n\t})\n\n\treturn { status: 'process-started', running: true } as const\n}\n\nexport async function runAppTests(app: App) {\n\tif (isDeployed) throw new Error('cannot run tests in deployed mode')\n\tconst key = app.name\n\n\tif (app.test.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-test' } as const\n\t}\n\n\tconst testProcess = spawn('npm', ['run', 'test', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: app.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\tAPP_SERVER_PORT:\n\t\t\t\tapp.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst output: Array<OutputLine> = []\n\tconst entry: TestProcessEntry = { process: testProcess, output }\n\tfunction handleStdOutData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stdout',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stderr',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stderr.on('data', handleStdErrData)\n\ttestProcess.on('exit', (code) => {\n\t\ttestProcess.stdout.off('data', handleStdOutData)\n\t\ttestProcess.stderr.off('data', handleStdErrData)\n\t\tentry.process = null\n\t\tentry.exitCode = code\n\t})\n\ttestProcesses.set(key, entry)\n\treturn testProcess\n}\n\nexport async function waitOnApp(app: App) {\n\tif (app.dev.type === 'script') {\n\t\tconst startTime = Date.now()\n\n\t\tconst retryInterval = 100\n\t\tconst timeout = 20_000\n\t\tlet lastError: unknown\n\t\twhile (Date.now() - startTime < timeout) {\n\t\t\ttry {\n\t\t\t\tconst url = await getWorkshopUrl(app.dev.portNumber)\n\t\t\t\tawait fetch(url, {\n\t\t\t\t\tmethod: 'HEAD',\n\t\t\t\t\theaders: { Accept: '*/*' },\n\t\t\t\t})\n\t\t\t\treturn { status: 'success' } as const\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, retryInterval))\n\t\t\t}\n\t\t}\n\n\t\treturn { status: 'error', error: getErrorMessage(lastError) } as const\n\t}\n\treturn null\n}\n\nexport function isPortAvailable(port: number | string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\t\tserver.unref()\n\t\tserver.on('error', () => resolve(false))\n\n\t\tserver.listen(Number(port), () => {\n\t\t\tserver.close(() => {\n\t\t\t\tresolve(true)\n\t\t\t})\n\t\t})\n\t})\n}\n\nexport async function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess?.process.pid) return false\n\t\tconst found = await findProcess('pid', devProcess.process.pid)\n\t\treturn found.length > 0\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function isTestRunning(app: { name: string }) {\n\ttry {\n\t\tconst testProcess = testProcesses.get(app.name)\n\t\tif (!testProcess) return false\n\t\tif (testProcess.process === null) return false\n\t\ttestProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function getTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.get(app.name)\n}\n\nexport function clearTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.delete(app.name)\n}\n\nexport function getProcesses() {\n\treturn { devProcesses, testProcesses }\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 findProcess from 'find-process'\nimport fkill from 'fkill'\nimport { type App } from './apps.server.js'\nimport { getWorkshopUrl } from './config.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', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: String(portNumber),\n\t\t\tAPP_SERVER_PORT: String(portNumber),\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst prefix = chalk[color](\n\t\t`[${app.name.replace(/^exercises\\./, '')}:${portNumber}]`,\n\t)\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stderr.on('data', handleStdErrData)\n\tdevProcesses.set(key, { color, process: appProcess, port: portNumber })\n\tappProcess.on('exit', (code) => {\n\t\tappProcess.stdout.off('data', handleStdOutData)\n\t\tappProcess.stderr.off('data', handleStdErrData)\n\t\tconsole.log(`${prefix} exited (${code})`)\n\t\tdevProcesses.delete(key)\n\t})\n\n\treturn { status: 'process-started', running: true } as const\n}\n\nexport async function runAppTests(app: App) {\n\tif (isDeployed) throw new Error('cannot run tests in deployed mode')\n\tconst key = app.name\n\n\tif (app.test.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-test' } as const\n\t}\n\n\tconst testProcess = spawn('npm', ['run', 'test', '--silent'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: app.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\tAPP_SERVER_PORT:\n\t\t\t\tapp.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst output: Array<OutputLine> = []\n\tconst entry: TestProcessEntry = { process: testProcess, output }\n\tfunction handleStdOutData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stdout',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stderr',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stderr.on('data', handleStdErrData)\n\ttestProcess.on('exit', (code) => {\n\t\ttestProcess.stdout.off('data', handleStdOutData)\n\t\ttestProcess.stderr.off('data', handleStdErrData)\n\t\tentry.process = null\n\t\tentry.exitCode = code\n\t})\n\ttestProcesses.set(key, entry)\n\treturn testProcess\n}\n\nexport async function waitOnApp(app: App) {\n\tif (app.dev.type === 'script') {\n\t\tconst startTime = Date.now()\n\n\t\tconst retryInterval = 100\n\t\tconst timeout = 20_000\n\t\tlet lastError: unknown\n\t\twhile (Date.now() - startTime < timeout) {\n\t\t\ttry {\n\t\t\t\tconst url = getWorkshopUrl(app.dev.portNumber)\n\t\t\t\tawait fetch(url, {\n\t\t\t\t\tmethod: 'HEAD',\n\t\t\t\t\theaders: { Accept: '*/*' },\n\t\t\t\t})\n\t\t\t\treturn { status: 'success' } as const\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, retryInterval))\n\t\t\t}\n\t\t}\n\n\t\treturn { status: 'error', error: getErrorMessage(lastError) } as const\n\t}\n\treturn null\n}\n\nexport function isPortAvailable(port: number | string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\t\tserver.unref()\n\t\tserver.on('error', () => resolve(false))\n\n\t\tserver.listen(Number(port), () => {\n\t\t\tserver.close(() => {\n\t\t\t\tresolve(true)\n\t\t\t})\n\t\t})\n\t})\n}\n\nexport async function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess?.process.pid) return false\n\t\tconst found = await findProcess('pid', devProcess.process.pid)\n\t\treturn found.length > 0\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function isTestRunning(app: { name: string }) {\n\ttry {\n\t\tconst testProcess = testProcesses.get(app.name)\n\t\tif (!testProcess) return false\n\t\tif (testProcess.process === null) return false\n\t\ttestProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function getTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.get(app.name)\n}\n\nexport function clearTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.delete(app.name)\n}\n\nexport function getProcesses() {\n\treturn { devProcesses, testProcesses }\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/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@epic-web/workshop-utils","version":"6.11.2","publishConfig":{"access":"public"},"type":"module","tshy":{"project":"./tsconfig.build.json","dialects":["esm"],"exports":{"./package.json":"./package.json","./apps.server":"./src/apps.server.ts","./diff.server":"./src/diff.server.ts","./env.server":"./src/env.server.ts","./epic-api.server":"./src/epic-api.server.ts","./user.server":"./src/user.server.ts","./cache.server":"./src/cache.server.ts","./config.server":"./src/config.server.ts","./db.server":"./src/db.server.ts","./timing.server":"./src/timing.server.ts","./modified-time.server":"./src/modified-time.server.ts","./compile-mdx.server":"./src/compile-mdx.server.ts","./git.server":"./src/git.server.ts","./iframe-sync":"./src/iframe-sync.ts","./playwright.server":"./src/playwright.server.ts","./notifications.server":"./src/notifications.server.ts","./process-manager.server":"./src/process-manager.server.ts","./test":"./src/test.ts","./utils.server":"./src/utils.server.ts","./utils":"./src/utils.ts"}},"exports":{"./package.json":"./package.json","./apps.server":{"import":{"types":"./dist/esm/apps.server.d.ts","default":"./dist/esm/apps.server.js"}},"./diff.server":{"import":{"types":"./dist/esm/diff.server.d.ts","default":"./dist/esm/diff.server.js"}},"./env.server":{"import":{"types":"./dist/esm/env.server.d.ts","default":"./dist/esm/env.server.js"}},"./epic-api.server":{"import":{"types":"./dist/esm/epic-api.server.d.ts","default":"./dist/esm/epic-api.server.js"}},"./user.server":{"import":{"types":"./dist/esm/user.server.d.ts","default":"./dist/esm/user.server.js"}},"./cache.server":{"import":{"types":"./dist/esm/cache.server.d.ts","default":"./dist/esm/cache.server.js"}},"./config.server":{"import":{"types":"./dist/esm/config.server.d.ts","default":"./dist/esm/config.server.js"}},"./db.server":{"import":{"types":"./dist/esm/db.server.d.ts","default":"./dist/esm/db.server.js"}},"./timing.server":{"import":{"types":"./dist/esm/timing.server.d.ts","default":"./dist/esm/timing.server.js"}},"./modified-time.server":{"import":{"types":"./dist/esm/modified-time.server.d.ts","default":"./dist/esm/modified-time.server.js"}},"./compile-mdx.server":{"import":{"types":"./dist/esm/compile-mdx.server.d.ts","default":"./dist/esm/compile-mdx.server.js"}},"./git.server":{"import":{"types":"./dist/esm/git.server.d.ts","default":"./dist/esm/git.server.js"}},"./iframe-sync":{"import":{"types":"./dist/esm/iframe-sync.d.ts","default":"./dist/esm/iframe-sync.js"}},"./playwright.server":{"import":{"types":"./dist/esm/playwright.server.d.ts","default":"./dist/esm/playwright.server.js"}},"./notifications.server":{"import":{"types":"./dist/esm/notifications.server.d.ts","default":"./dist/esm/notifications.server.js"}},"./process-manager.server":{"import":{"types":"./dist/esm/process-manager.server.d.ts","default":"./dist/esm/process-manager.server.js"}},"./test":{"import":{"types":"./dist/esm/test.d.ts","default":"./dist/esm/test.js"}},"./utils.server":{"import":{"types":"./dist/esm/utils.server.d.ts","default":"./dist/esm/utils.server.js"}},"./utils":{"import":{"types":"./dist/esm/utils.d.ts","default":"./dist/esm/utils.js"}}},"files":["dist"],"scripts":{"typecheck":"tsc --noEmit","build":"tshy","build:watch":"nx watch --projects=@epic-web/workshop-utils -- nx run \\$NX_PROJECT_NAME:build"},"dependencies":{"@epic-web/cachified":"^5.6.0","@epic-web/invariant":"^1.0.0","@epic-web/remember":"^1.1.0","@kentcdodds/md-temp":"^10.0.1","@mdx-js/mdx":"^3.1.0","@paralleldrive/cuid2":"^2.2.2","@playwright/test":"^1.53.2","@react-router/node":"^7.6.3","@testing-library/dom":"^10.4.0","@testing-library/jest-dom":"^6.6.3","@total-typescript/ts-reset":"^0.6.1","@types/chai":"^5.2.2","@types/chai-dom":"^1.11.3","@vitest/expect":"^3.2.4","chai":"^5.2.0","chai-dom":"^1.12.1","chalk":"^5.4.1","chokidar":"^4.0.3","close-with-grace":"^2.2.0","cookie":"^1.0.2","cross-spawn":"^7.0.6","dayjs":"^1.11.13","esbuild":"^0.25.5","execa":"^9.6.0","find-process":"^1.4.10","fkill":"^9.0.0","fs-extra":"^11.3.0","globby":"^14.1.0","ignore":"^7.0.5","json5":"^2.2.3","lru-cache":"^11.1.0","lz-string":"^1.5.0","md5-hex":"^5.0.0","mdast-util-mdx-jsx":"^3.2.0","mdx-bundler":"^10.1.1","p-queue":"^8.1.0","parse-git-diff":"^0.0.19","rehype":"^13.0.2","rehype-autolink-headings":"^7.1.0","remark":"^15.0.1","remark-emoji":"^5.0.1","remark-gfm":"^4.0.1","shiki":"^3.7.0","unified":"^11.0.5","unist-util-remove-position":"^5.0.0","unist-util-visit":"^5.0.0","zod":"^3.25.71"},"devDependencies":{"@types/hast":"^3.0.4","@types/mdast":"^4.0.4","@types/node":"^24.0.10","tshy":"^3.0.2"},"repository":{"type":"git","url":"https://github.com/epicweb-dev/epicshop.git","directory":"packages/workshop-utils"}}
1
+ {"name":"@epic-web/workshop-utils","version":"6.11.4","publishConfig":{"access":"public"},"type":"module","tshy":{"project":"./tsconfig.build.json","dialects":["esm"],"exports":{"./package.json":"./package.json","./apps.server":"./src/apps.server.ts","./diff.server":"./src/diff.server.ts","./env.server":"./src/env.server.ts","./epic-api.server":"./src/epic-api.server.ts","./user.server":"./src/user.server.ts","./cache.server":"./src/cache.server.ts","./config.server":"./src/config.server.ts","./db.server":"./src/db.server.ts","./timing.server":"./src/timing.server.ts","./modified-time.server":"./src/modified-time.server.ts","./compile-mdx.server":"./src/compile-mdx.server.ts","./git.server":"./src/git.server.ts","./iframe-sync":"./src/iframe-sync.ts","./playwright.server":"./src/playwright.server.ts","./notifications.server":"./src/notifications.server.ts","./process-manager.server":"./src/process-manager.server.ts","./test":"./src/test.ts","./utils.server":"./src/utils.server.ts","./utils":"./src/utils.ts"}},"exports":{"./package.json":"./package.json","./apps.server":{"import":{"types":"./dist/esm/apps.server.d.ts","default":"./dist/esm/apps.server.js"}},"./diff.server":{"import":{"types":"./dist/esm/diff.server.d.ts","default":"./dist/esm/diff.server.js"}},"./env.server":{"import":{"types":"./dist/esm/env.server.d.ts","default":"./dist/esm/env.server.js"}},"./epic-api.server":{"import":{"types":"./dist/esm/epic-api.server.d.ts","default":"./dist/esm/epic-api.server.js"}},"./user.server":{"import":{"types":"./dist/esm/user.server.d.ts","default":"./dist/esm/user.server.js"}},"./cache.server":{"import":{"types":"./dist/esm/cache.server.d.ts","default":"./dist/esm/cache.server.js"}},"./config.server":{"import":{"types":"./dist/esm/config.server.d.ts","default":"./dist/esm/config.server.js"}},"./db.server":{"import":{"types":"./dist/esm/db.server.d.ts","default":"./dist/esm/db.server.js"}},"./timing.server":{"import":{"types":"./dist/esm/timing.server.d.ts","default":"./dist/esm/timing.server.js"}},"./modified-time.server":{"import":{"types":"./dist/esm/modified-time.server.d.ts","default":"./dist/esm/modified-time.server.js"}},"./compile-mdx.server":{"import":{"types":"./dist/esm/compile-mdx.server.d.ts","default":"./dist/esm/compile-mdx.server.js"}},"./git.server":{"import":{"types":"./dist/esm/git.server.d.ts","default":"./dist/esm/git.server.js"}},"./iframe-sync":{"import":{"types":"./dist/esm/iframe-sync.d.ts","default":"./dist/esm/iframe-sync.js"}},"./playwright.server":{"import":{"types":"./dist/esm/playwright.server.d.ts","default":"./dist/esm/playwright.server.js"}},"./notifications.server":{"import":{"types":"./dist/esm/notifications.server.d.ts","default":"./dist/esm/notifications.server.js"}},"./process-manager.server":{"import":{"types":"./dist/esm/process-manager.server.d.ts","default":"./dist/esm/process-manager.server.js"}},"./test":{"import":{"types":"./dist/esm/test.d.ts","default":"./dist/esm/test.js"}},"./utils.server":{"import":{"types":"./dist/esm/utils.server.d.ts","default":"./dist/esm/utils.server.js"}},"./utils":{"import":{"types":"./dist/esm/utils.d.ts","default":"./dist/esm/utils.js"}}},"files":["dist"],"scripts":{"typecheck":"tsc --noEmit","build":"tshy","build:watch":"nx watch --projects=@epic-web/workshop-utils -- nx run \\$NX_PROJECT_NAME:build"},"dependencies":{"@epic-web/cachified":"^5.6.0","@epic-web/invariant":"^1.0.0","@epic-web/remember":"^1.1.0","@kentcdodds/md-temp":"^10.0.1","@mdx-js/mdx":"^3.1.0","@paralleldrive/cuid2":"^2.2.2","@playwright/test":"^1.53.2","@react-router/node":"^7.6.3","@testing-library/dom":"^10.4.0","@testing-library/jest-dom":"^6.6.3","@total-typescript/ts-reset":"^0.6.1","@types/chai":"^5.2.2","@types/chai-dom":"^1.11.3","@vitest/expect":"^3.2.4","chai":"^5.2.0","chai-dom":"^1.12.1","chalk":"^5.4.1","chokidar":"^4.0.3","close-with-grace":"^2.2.0","cookie":"^1.0.2","cross-spawn":"^7.0.6","dayjs":"^1.11.13","esbuild":"^0.25.5","execa":"^9.6.0","find-process":"^1.4.10","fkill":"^9.0.0","fs-extra":"^11.3.0","globby":"^14.1.0","ignore":"^7.0.5","json5":"^2.2.3","lru-cache":"^11.1.0","lz-string":"^1.5.0","md5-hex":"^5.0.0","mdast-util-mdx-jsx":"^3.2.0","mdx-bundler":"^10.1.1","p-queue":"^8.1.0","parse-git-diff":"^0.0.19","rehype":"^13.0.2","rehype-autolink-headings":"^7.1.0","remark":"^15.0.1","remark-emoji":"^5.0.1","remark-gfm":"^4.0.1","shiki":"^3.7.0","unified":"^11.0.5","unist-util-remove-position":"^5.0.0","unist-util-visit":"^5.0.0","zod":"^3.25.71"},"devDependencies":{"@types/hast":"^3.0.4","@types/mdast":"^4.0.4","@types/node":"^24.0.10","tshy":"^3.0.2"},"repository":{"type":"git","url":"https://github.com/epicweb-dev/epicshop.git","directory":"packages/workshop-utils"}}