@epic-web/workshop-utils 6.47.0 → 6.47.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.server.d.ts","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAcjC,CAAA;AAsDF,QAAA,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAnBvB;QACR,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;QACxB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;QAC/B,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;QACpC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KACxB;;;;;;;;;;;;;;;;EAgBiC,CAAA;AAEnC,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAG/E,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEvB,CAAA;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,OAAO,GAClB,qBAAqB,GAAG,IAAI,CAgB9B;AA2BD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,UAE1C;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAiClD;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,0BA0EA;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;GA0ElD"}
1
+ {"version":3,"file":"config.server.d.ts","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAcjC,CAAA;AAsDF,QAAA,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAnBvB;QACR,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;QACxB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;QAC/B,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;QACpC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KACxB;;;;;;;;;;;;;;;;EAgBiC,CAAA;AAEnC,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAG/E,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEvB,CAAA;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,OAAO,GAClB,qBAAqB,GAAG,IAAI,CAgB9B;AAiCD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,UAE1C;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAiClD;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,0BA0EA;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;GA0ElD"}
@@ -141,6 +141,12 @@ export function parseEpicshopConfig(packageJson) {
141
141
  let configCache = null;
142
142
  // Utility to read and parse the root package.json
143
143
  function readRootPkgJson() {
144
+ const contextCwd = getEnv().EPICSHOP_CONTEXT_CWD;
145
+ if (!contextCwd) {
146
+ const error = new Error('Not in a workshop directory');
147
+ error.name = 'NotInWorkshopDirectoryError';
148
+ throw error;
149
+ }
144
150
  const packageJsonPath = getRootPkgJsonPath();
145
151
  try {
146
152
  const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
@@ -1 +1 @@
1
- {"version":3,"file":"config.server.js","sourceRoot":"","sources":["../../src/config.server.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/order -- this must be first\nimport { getEnv } from './init-env.js'\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { z } from 'zod'\nimport { handleGitHubRepoAndRoot } from './utils.js'\n\nconst getRootPkgJsonPath = () =>\n\tpath.join(getEnv().EPICSHOP_CONTEXT_CWD, '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\nconst BaseProductSchema = z.object({\n\thost: z.string().optional(),\n\tdisplayName: z.string().optional(),\n\tdisplayNameShort: z.string().optional(),\n\tslug: z.string().optional(),\n})\n\nconst BaseWorkshopConfigFields = {\n\ttitle: z.string().optional(),\n\tsubtitle: z.string().optional(),\n\tinstructor: InstructorSchema.optional(),\n\tproduct: BaseProductSchema.optional(),\n}\n\nfunction transformProductFields<\n\tT extends {\n\t\tproduct?: {\n\t\t\thost?: string\n\t\t\tdisplayName?: string\n\t\t\tdisplayNameShort?: string\n\t\t\tslug?: string\n\t\t}\n\t},\n>(\n\tdata: T,\n): T & {\n\tproduct: {\n\t\thost: string | undefined\n\t\tdisplayName: string | undefined\n\t\tdisplayNameShort: string | undefined\n\t\tslug: string | undefined\n\t}\n} {\n\tconst product = data.product ?? {}\n\treturn {\n\t\t...data,\n\t\tproduct: {\n\t\t\thost: product.host,\n\t\t\tdisplayName: product.displayName,\n\t\t\tdisplayNameShort: product.displayNameShort ?? product.displayName,\n\t\t\tslug: product.slug,\n\t\t},\n\t}\n}\n\nconst PartialWorkshopConfigSchema = z\n\t.object(BaseWorkshopConfigFields)\n\t.transform(transformProductFields)\n\nexport type PartialWorkshopConfig = z.infer<typeof PartialWorkshopConfigSchema>\n\n// most defaults are for backwards compatibility\nconst WorkshopConfigSchema = z\n\t.object({\n\t\t...BaseWorkshopConfigFields,\n\t\ttitle: z.string(),\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().optional(),\n\t\t\t\tdiscordTags: z.array(z.string()).optional(),\n\t\t\t})\n\t\t\t.default({}),\n\t\tgithubRepo: z\n\t\t\t.string()\n\t\t\t.transform((githubRepo) => githubRepo ?? getEnv().EPICSHOP_GITHUB_REPO),\n\t\tgithubRoot: z\n\t\t\t.string()\n\t\t\t.transform((githubRoot) => githubRoot ?? getEnv().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\tsidecarProcesses: z.record(z.string(), z.string()).optional().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},\n\t\t}\n\t})\n\nexport type WorkshopConfig = z.infer<typeof WorkshopConfigSchema>\n\n/**\n * Parse epicshop config from an arbitrary package.json object.\n * Unlike getWorkshopConfig(), this doesn't require EPICSHOP_CONTEXT_CWD\n * and returns partial/optional config suitable for external repos.\n */\nexport function parseEpicshopConfig(\n\tpackageJson: unknown,\n): PartialWorkshopConfig | null {\n\tif (\n\t\ttypeof packageJson !== 'object' ||\n\t\tpackageJson === null ||\n\t\t!('epicshop' in packageJson)\n\t) {\n\t\treturn null\n\t}\n\n\tconst epicshopConfig = (packageJson as { epicshop: unknown }).epicshop\n\tconst result = PartialWorkshopConfigSchema.safeParse(epicshopConfig)\n\tif (!result.success) {\n\t\treturn null\n\t}\n\n\treturn result.data\n}\n\nlet configCache: WorkshopConfig | null = null\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 * This used to support subdomains on localhost, but that caused too many issues.\n */\nexport function getWorkshopUrl(port: number) {\n\treturn `http://localhost:${port}`\n}\n\nexport function getWorkshopConfig(): WorkshopConfig {\n\t// If config is cached, use it\n\tif (configCache) return configCache\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 = parsedConfig\n\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(\n\t\t`${getEnv().EPICSHOP_CONTEXT_CWD}${path.sep}`,\n\t\t'',\n\t)\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,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtC,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,kBAAkB,GAAG,GAAG,EAAE,CAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAA;AAEzD,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,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAA;AAEF,MAAM,wBAAwB,GAAG;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,UAAU,EAAE,gBAAgB,CAAC,QAAQ,EAAE;IACvC,OAAO,EAAE,iBAAiB,CAAC,QAAQ,EAAE;CACrC,CAAA;AAED,SAAS,sBAAsB,CAU9B,IAAO;IASP,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;IAClC,OAAO;QACN,GAAG,IAAI;QACP,OAAO,EAAE;YACR,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,WAAW;YACjE,IAAI,EAAE,OAAO,CAAC,IAAI;SAClB;KACD,CAAA;AACF,CAAC;AAED,MAAM,2BAA2B,GAAG,CAAC;KACnC,MAAM,CAAC,wBAAwB,CAAC;KAChC,SAAS,CAAC,sBAAsB,CAAC,CAAA;AAInC,gDAAgD;AAChD,MAAM,oBAAoB,GAAG,CAAC;KAC5B,MAAM,CAAC;IACP,GAAG,wBAAwB;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,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,QAAQ,EAAE;QACvC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KAC3C,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,UAAU,EAAE,CAAC;SACX,MAAM,EAAE;SACR,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC,oBAAoB,CAAC;IACxE,UAAU,EAAE,CAAC;SACX,MAAM,EAAE;SACR,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC,oBAAoB,CAAC;IACxE,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;IACb,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACzE,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;SAC1D;KACD,CAAA;AACF,CAAC,CAAC,CAAA;AAIH;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAClC,WAAoB;IAEpB,IACC,OAAO,WAAW,KAAK,QAAQ;QAC/B,WAAW,KAAK,IAAI;QACpB,CAAC,CAAC,UAAU,IAAI,WAAW,CAAC,EAC3B,CAAC;QACF,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,MAAM,cAAc,GAAI,WAAqC,CAAC,QAAQ,CAAA;IACtE,MAAM,MAAM,GAAG,2BAA2B,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;IACpE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAA;AACnB,CAAC;AAED,IAAI,WAAW,GAA0B,IAAI,CAAA;AAE7C,kDAAkD;AAClD,SAAS,eAAe;IACvB,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,oBAAoB,CAAA;IAChD,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;QACtD,KAAK,CAAC,IAAI,GAAG,6BAA6B,CAAA;QAC1C,MAAM,KAAK,CAAA;IACZ,CAAC;IACD,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;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IAC1C,OAAO,oBAAoB,IAAI,EAAE,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAChC,8BAA8B;IAC9B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAA;IAEnC,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,GAAG,YAAY,CAAA;QAE1B,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,CACpC,GAAG,MAAM,EAAE,CAAC,oBAAoB,GAAG,IAAI,CAAC,GAAG,EAAE,EAC7C,EAAE,CACF,CAAA;IAED,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":["// eslint-disable-next-line import/order -- this must be first\nimport { getEnv } from './init-env.js'\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { z } from 'zod'\nimport { handleGitHubRepoAndRoot } from './utils.js'\n\nconst getRootPkgJsonPath = () =>\n\tpath.join(getEnv().EPICSHOP_CONTEXT_CWD, '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\nconst BaseProductSchema = z.object({\n\thost: z.string().optional(),\n\tdisplayName: z.string().optional(),\n\tdisplayNameShort: z.string().optional(),\n\tslug: z.string().optional(),\n})\n\nconst BaseWorkshopConfigFields = {\n\ttitle: z.string().optional(),\n\tsubtitle: z.string().optional(),\n\tinstructor: InstructorSchema.optional(),\n\tproduct: BaseProductSchema.optional(),\n}\n\nfunction transformProductFields<\n\tT extends {\n\t\tproduct?: {\n\t\t\thost?: string\n\t\t\tdisplayName?: string\n\t\t\tdisplayNameShort?: string\n\t\t\tslug?: string\n\t\t}\n\t},\n>(\n\tdata: T,\n): T & {\n\tproduct: {\n\t\thost: string | undefined\n\t\tdisplayName: string | undefined\n\t\tdisplayNameShort: string | undefined\n\t\tslug: string | undefined\n\t}\n} {\n\tconst product = data.product ?? {}\n\treturn {\n\t\t...data,\n\t\tproduct: {\n\t\t\thost: product.host,\n\t\t\tdisplayName: product.displayName,\n\t\t\tdisplayNameShort: product.displayNameShort ?? product.displayName,\n\t\t\tslug: product.slug,\n\t\t},\n\t}\n}\n\nconst PartialWorkshopConfigSchema = z\n\t.object(BaseWorkshopConfigFields)\n\t.transform(transformProductFields)\n\nexport type PartialWorkshopConfig = z.infer<typeof PartialWorkshopConfigSchema>\n\n// most defaults are for backwards compatibility\nconst WorkshopConfigSchema = z\n\t.object({\n\t\t...BaseWorkshopConfigFields,\n\t\ttitle: z.string(),\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().optional(),\n\t\t\t\tdiscordTags: z.array(z.string()).optional(),\n\t\t\t})\n\t\t\t.default({}),\n\t\tgithubRepo: z\n\t\t\t.string()\n\t\t\t.transform((githubRepo) => githubRepo ?? getEnv().EPICSHOP_GITHUB_REPO),\n\t\tgithubRoot: z\n\t\t\t.string()\n\t\t\t.transform((githubRoot) => githubRoot ?? getEnv().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\tsidecarProcesses: z.record(z.string(), z.string()).optional().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},\n\t\t}\n\t})\n\nexport type WorkshopConfig = z.infer<typeof WorkshopConfigSchema>\n\n/**\n * Parse epicshop config from an arbitrary package.json object.\n * Unlike getWorkshopConfig(), this doesn't require EPICSHOP_CONTEXT_CWD\n * and returns partial/optional config suitable for external repos.\n */\nexport function parseEpicshopConfig(\n\tpackageJson: unknown,\n): PartialWorkshopConfig | null {\n\tif (\n\t\ttypeof packageJson !== 'object' ||\n\t\tpackageJson === null ||\n\t\t!('epicshop' in packageJson)\n\t) {\n\t\treturn null\n\t}\n\n\tconst epicshopConfig = (packageJson as { epicshop: unknown }).epicshop\n\tconst result = PartialWorkshopConfigSchema.safeParse(epicshopConfig)\n\tif (!result.success) {\n\t\treturn null\n\t}\n\n\treturn result.data\n}\n\nlet configCache: WorkshopConfig | null = null\n\n// Utility to read and parse the root package.json\nfunction readRootPkgJson(): any {\n\tconst contextCwd = getEnv().EPICSHOP_CONTEXT_CWD\n\tif (!contextCwd) {\n\t\tconst error = new Error('Not in a workshop directory')\n\t\terror.name = 'NotInWorkshopDirectoryError'\n\t\tthrow error\n\t}\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 * This used to support subdomains on localhost, but that caused too many issues.\n */\nexport function getWorkshopUrl(port: number) {\n\treturn `http://localhost:${port}`\n}\n\nexport function getWorkshopConfig(): WorkshopConfig {\n\t// If config is cached, use it\n\tif (configCache) return configCache\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 = parsedConfig\n\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(\n\t\t`${getEnv().EPICSHOP_CONTEXT_CWD}${path.sep}`,\n\t\t'',\n\t)\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"]}
@@ -16,6 +16,7 @@ export type Workshop = {
16
16
  export type WorkshopsConfig = z.infer<typeof ConfigSchema>;
17
17
  export declare function loadConfig(): Promise<WorkshopsConfig>;
18
18
  export declare function saveConfig(config: WorkshopsConfig): Promise<void>;
19
+ export declare function deleteConfig(): Promise<void>;
19
20
  export declare function getReposDirectory(): Promise<string>;
20
21
  export declare function isReposDirectoryConfigured(): Promise<boolean>;
21
22
  export declare function getDefaultReposDir(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"workshops.server.d.ts","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,YAAY;;;;;;EAEhB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AA2B1D,wBAAsB,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC,CAS3D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAGnE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CA4CzD;AAED,wBAAsB,WAAW,CAChC,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQ/B;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvE;AAED,wBAAsB,iBAAiB,CACtC,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAI/B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,kBAAkB,EAAE,OAAO,CAAA;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC,CA6HD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE"}
1
+ {"version":3,"file":"workshops.server.d.ts","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,YAAY;;;;;;EAEhB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AA2B1D,wBAAsB,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC,CAS3D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAOlD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAGnE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CA4CzD;AAED,wBAAsB,WAAW,CAChC,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQ/B;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvE;AAED,wBAAsB,iBAAiB,CACtC,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAI/B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,kBAAkB,EAAE,OAAO,CAAA;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC,CA6HD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE"}
@@ -61,6 +61,15 @@ export async function saveConfig(config) {
61
61
  const configPath = resolveConfigPath();
62
62
  await atomicWriteJSON(configPath, config);
63
63
  }
64
+ export async function deleteConfig() {
65
+ const configPath = resolveConfigPath();
66
+ try {
67
+ await fs.unlink(configPath);
68
+ }
69
+ catch {
70
+ // File doesn't exist, which is fine
71
+ }
72
+ }
64
73
  export async function getReposDirectory() {
65
74
  const config = await loadConfig();
66
75
  return config.reposDirectory || getDefaultReposDirectory();
@@ -1 +1 @@
1
- {"version":3,"file":"workshops.server.js","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { z } from 'zod'\nimport { resolvePrimaryDir } from './data-storage.server.js'\n\nconst CONFIG_FILE = 'workshops-config.json'\n\n// Schema for the epicshop property in package.json\nconst EpicshopConfigSchema = z.object({\n\ttitle: z.string(),\n\tsubtitle: z.string().optional(),\n\tproduct: z\n\t\t.object({\n\t\t\thost: z.string().optional(),\n\t\t\tslug: z.string().optional(),\n\t\t\tlogo: z.string().optional(),\n\t\t\tdisplayName: z.string().optional(),\n\t\t\tdisplayNameShort: z.string().optional(),\n\t\t})\n\t\t.optional(),\n})\n\n// Schema for workshop configuration (stored settings only)\nconst ConfigSchema = z.object({\n\treposDirectory: z.string().optional(),\n})\n\nexport type Workshop = {\n\tname: string\n\ttitle: string\n\tsubtitle?: string\n\trepoName: string\n\tpath: string\n}\n\nexport type WorkshopsConfig = z.infer<typeof ConfigSchema>\n\nfunction getDefaultReposDirectory(): string {\n\treturn path.join(os.homedir(), 'epic-workshops')\n}\n\nfunction resolveConfigPath(): string {\n\treturn path.join(resolvePrimaryDir(), CONFIG_FILE)\n}\n\nasync function ensureDir(dir: string) {\n\ttry {\n\t\tawait fs.mkdir(dir, { recursive: true, mode: 0o700 })\n\t} catch {}\n\ttry {\n\t\tawait fs.chmod(dir, 0o700)\n\t} catch {}\n}\n\nasync function atomicWriteJSON(filePath: string, data: unknown) {\n\tconst dir = path.dirname(filePath)\n\tawait ensureDir(dir)\n\tconst tmp = path.join(dir, `.tmp-${randomUUID()}`)\n\tawait fs.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 0o600 })\n\tawait fs.rename(tmp, filePath)\n}\n\nexport async function loadConfig(): Promise<WorkshopsConfig> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tconst txt = await fs.readFile(configPath, 'utf8')\n\t\tconst data = JSON.parse(txt)\n\t\treturn ConfigSchema.parse(data)\n\t} catch {\n\t\treturn {}\n\t}\n}\n\nexport async function saveConfig(config: WorkshopsConfig): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\tawait atomicWriteJSON(configPath, config)\n}\n\nexport async function getReposDirectory(): Promise<string> {\n\tconst config = await loadConfig()\n\treturn config.reposDirectory || getDefaultReposDirectory()\n}\n\nexport async function isReposDirectoryConfigured(): Promise<boolean> {\n\tconst config = await loadConfig()\n\treturn Boolean(config.reposDirectory)\n}\n\nexport function getDefaultReposDir(): string {\n\treturn getDefaultReposDirectory()\n}\n\nexport async function setReposDirectory(directory: string): Promise<void> {\n\tconst config = await loadConfig()\n\tconfig.reposDirectory = path.resolve(directory)\n\tawait saveConfig(config)\n}\n\n/**\n * Scan a directory for workshops (directories with package.json containing \"epicshop\" property)\n */\nexport async function listWorkshops(): Promise<Workshop[]> {\n\tconst reposDir = await getReposDirectory()\n\n\t// Check if directory exists\n\ttry {\n\t\tawait fs.access(reposDir)\n\t} catch {\n\t\treturn []\n\t}\n\n\tconst entries = await fs.readdir(reposDir, { withFileTypes: true })\n\tconst workshops: Workshop[] = []\n\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue\n\n\t\tconst workshopPath = path.join(reposDir, entry.name)\n\t\tconst pkgPath = path.join(workshopPath, 'package.json')\n\n\t\ttry {\n\t\t\tconst pkgContent = await fs.readFile(pkgPath, 'utf8')\n\t\t\tconst pkg = JSON.parse(pkgContent) as {\n\t\t\t\tname?: string\n\t\t\t\tepicshop?: unknown\n\t\t\t}\n\n\t\t\tif (pkg.epicshop) {\n\t\t\t\tconst epicshopConfig = EpicshopConfigSchema.safeParse(pkg.epicshop)\n\t\t\t\tif (epicshopConfig.success) {\n\t\t\t\t\tworkshops.push({\n\t\t\t\t\t\tname: pkg.name || entry.name,\n\t\t\t\t\t\ttitle: epicshopConfig.data.title,\n\t\t\t\t\t\tsubtitle: epicshopConfig.data.subtitle,\n\t\t\t\t\t\trepoName: entry.name,\n\t\t\t\t\t\tpath: workshopPath,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not a valid workshop directory, skip\n\t\t}\n\t}\n\n\treturn workshops\n}\n\nexport async function getWorkshop(\n\tidOrName: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.find(\n\t\t(w) =>\n\t\t\tw.name.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.repoName.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.title.toLowerCase() === idOrName.toLowerCase(),\n\t)\n}\n\nexport async function workshopExists(repoName: string): Promise<boolean> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.some(\n\t\t(w) => w.repoName.toLowerCase() === repoName.toLowerCase(),\n\t)\n}\n\nexport async function getWorkshopByPath(\n\tworkshopPath: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\tconst resolvedPath = path.resolve(workshopPath)\n\treturn workshops.find((w) => path.resolve(w.path) === resolvedPath)\n}\n\n/**\n * Check for unpushed changes in a git repository\n * Returns info about unpushed commits across all branches\n */\nexport async function getUnpushedChanges(repoPath: string): Promise<{\n\thasUnpushed: boolean\n\tbranches: Array<{ name: string; unpushedCount: number }>\n\tuncommittedChanges: boolean\n\tsummary: string[]\n}> {\n\tconst { execSync } = await import('node:child_process')\n\n\tconst result = {\n\t\thasUnpushed: false,\n\t\tbranches: [] as Array<{ name: string; unpushedCount: number }>,\n\t\tuncommittedChanges: false,\n\t\tsummary: [] as string[],\n\t}\n\n\ttry {\n\t\t// Check if it's a git repository\n\t\texecSync('git rev-parse --git-dir', {\n\t\t\tcwd: repoPath,\n\t\t\tstdio: 'pipe',\n\t\t})\n\t} catch {\n\t\t// Not a git repository\n\t\treturn result\n\t}\n\n\ttry {\n\t\t// Check for uncommitted changes\n\t\tconst status = execSync('git status --porcelain', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tif (status) {\n\t\t\tresult.uncommittedChanges = true\n\t\t\tresult.hasUnpushed = true\n\t\t\tconst lines = status.split('\\n')\n\t\t\tconst modified = lines.filter(\n\t\t\t\t(l) => l.startsWith(' M') || l.startsWith('M '),\n\t\t\t).length\n\t\t\tconst added = lines.filter(\n\t\t\t\t(l) => l.startsWith('A ') || l.startsWith('??'),\n\t\t\t).length\n\t\t\tconst deleted = lines.filter(\n\t\t\t\t(l) => l.startsWith(' D') || l.startsWith('D '),\n\t\t\t).length\n\n\t\t\tconst parts = []\n\t\t\tif (modified > 0) parts.push(`${modified} modified`)\n\t\t\tif (added > 0) parts.push(`${added} untracked/added`)\n\t\t\tif (deleted > 0) parts.push(`${deleted} deleted`)\n\t\t\tif (parts.length > 0) {\n\t\t\t\tresult.summary.push(`Uncommitted changes: ${parts.join(', ')}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get all local branches\n\t\tconst branchOutput = execSync('git branch', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tconst branches = branchOutput\n\t\t\t.split('\\n')\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, '').trim())\n\t\t\t.filter(Boolean)\n\n\t\tfor (const branch of branches) {\n\t\t\ttry {\n\t\t\t\t// Check if branch has an upstream\n\t\t\t\tconst upstream = execSync(\n\t\t\t\t\t`git rev-parse --abbrev-ref ${branch}@{upstream}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\t// Count unpushed commits\n\t\t\t\tconst unpushedOutput = execSync(\n\t\t\t\t\t`git rev-list --count ${upstream}..${branch}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\tconst unpushedCount = parseInt(unpushedOutput, 10)\n\t\t\t\tif (unpushedCount > 0) {\n\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount })\n\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t`Branch \"${branch}\": ${unpushedCount} unpushed commit${unpushedCount > 1 ? 's' : ''}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Branch has no upstream, check if it has any commits not in any remote\n\t\t\t\ttry {\n\t\t\t\t\tconst allRemotes = execSync('git remote', {\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t}).trim()\n\n\t\t\t\t\tif (allRemotes) {\n\t\t\t\t\t\t// Branch exists but has no upstream tracking\n\t\t\t\t\t\tconst commitCount = execSync(`git rev-list --count ${branch}`, {\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\t}).trim()\n\n\t\t\t\t\t\tconst count = parseInt(commitCount, 10)\n\t\t\t\t\t\tif (count > 0) {\n\t\t\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount: count })\n\t\t\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t\t\t`Branch \"${branch}\": ${count} local commit${count > 1 ? 's' : ''} (no upstream)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors for individual branches\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Error checking git status, assume no unpushed changes\n\t}\n\n\treturn result\n}\n\n/**\n * Delete a workshop directory\n */\nexport async function deleteWorkshop(workshopPath: string): Promise<void> {\n\tawait fs.rm(workshopPath, { recursive: true, force: true })\n}\n"]}
1
+ {"version":3,"file":"workshops.server.js","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { z } from 'zod'\nimport { resolvePrimaryDir } from './data-storage.server.js'\n\nconst CONFIG_FILE = 'workshops-config.json'\n\n// Schema for the epicshop property in package.json\nconst EpicshopConfigSchema = z.object({\n\ttitle: z.string(),\n\tsubtitle: z.string().optional(),\n\tproduct: z\n\t\t.object({\n\t\t\thost: z.string().optional(),\n\t\t\tslug: z.string().optional(),\n\t\t\tlogo: z.string().optional(),\n\t\t\tdisplayName: z.string().optional(),\n\t\t\tdisplayNameShort: z.string().optional(),\n\t\t})\n\t\t.optional(),\n})\n\n// Schema for workshop configuration (stored settings only)\nconst ConfigSchema = z.object({\n\treposDirectory: z.string().optional(),\n})\n\nexport type Workshop = {\n\tname: string\n\ttitle: string\n\tsubtitle?: string\n\trepoName: string\n\tpath: string\n}\n\nexport type WorkshopsConfig = z.infer<typeof ConfigSchema>\n\nfunction getDefaultReposDirectory(): string {\n\treturn path.join(os.homedir(), 'epic-workshops')\n}\n\nfunction resolveConfigPath(): string {\n\treturn path.join(resolvePrimaryDir(), CONFIG_FILE)\n}\n\nasync function ensureDir(dir: string) {\n\ttry {\n\t\tawait fs.mkdir(dir, { recursive: true, mode: 0o700 })\n\t} catch {}\n\ttry {\n\t\tawait fs.chmod(dir, 0o700)\n\t} catch {}\n}\n\nasync function atomicWriteJSON(filePath: string, data: unknown) {\n\tconst dir = path.dirname(filePath)\n\tawait ensureDir(dir)\n\tconst tmp = path.join(dir, `.tmp-${randomUUID()}`)\n\tawait fs.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 0o600 })\n\tawait fs.rename(tmp, filePath)\n}\n\nexport async function loadConfig(): Promise<WorkshopsConfig> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tconst txt = await fs.readFile(configPath, 'utf8')\n\t\tconst data = JSON.parse(txt)\n\t\treturn ConfigSchema.parse(data)\n\t} catch {\n\t\treturn {}\n\t}\n}\n\nexport async function saveConfig(config: WorkshopsConfig): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\tawait atomicWriteJSON(configPath, config)\n}\n\nexport async function deleteConfig(): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tawait fs.unlink(configPath)\n\t} catch {\n\t\t// File doesn't exist, which is fine\n\t}\n}\n\nexport async function getReposDirectory(): Promise<string> {\n\tconst config = await loadConfig()\n\treturn config.reposDirectory || getDefaultReposDirectory()\n}\n\nexport async function isReposDirectoryConfigured(): Promise<boolean> {\n\tconst config = await loadConfig()\n\treturn Boolean(config.reposDirectory)\n}\n\nexport function getDefaultReposDir(): string {\n\treturn getDefaultReposDirectory()\n}\n\nexport async function setReposDirectory(directory: string): Promise<void> {\n\tconst config = await loadConfig()\n\tconfig.reposDirectory = path.resolve(directory)\n\tawait saveConfig(config)\n}\n\n/**\n * Scan a directory for workshops (directories with package.json containing \"epicshop\" property)\n */\nexport async function listWorkshops(): Promise<Workshop[]> {\n\tconst reposDir = await getReposDirectory()\n\n\t// Check if directory exists\n\ttry {\n\t\tawait fs.access(reposDir)\n\t} catch {\n\t\treturn []\n\t}\n\n\tconst entries = await fs.readdir(reposDir, { withFileTypes: true })\n\tconst workshops: Workshop[] = []\n\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue\n\n\t\tconst workshopPath = path.join(reposDir, entry.name)\n\t\tconst pkgPath = path.join(workshopPath, 'package.json')\n\n\t\ttry {\n\t\t\tconst pkgContent = await fs.readFile(pkgPath, 'utf8')\n\t\t\tconst pkg = JSON.parse(pkgContent) as {\n\t\t\t\tname?: string\n\t\t\t\tepicshop?: unknown\n\t\t\t}\n\n\t\t\tif (pkg.epicshop) {\n\t\t\t\tconst epicshopConfig = EpicshopConfigSchema.safeParse(pkg.epicshop)\n\t\t\t\tif (epicshopConfig.success) {\n\t\t\t\t\tworkshops.push({\n\t\t\t\t\t\tname: pkg.name || entry.name,\n\t\t\t\t\t\ttitle: epicshopConfig.data.title,\n\t\t\t\t\t\tsubtitle: epicshopConfig.data.subtitle,\n\t\t\t\t\t\trepoName: entry.name,\n\t\t\t\t\t\tpath: workshopPath,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not a valid workshop directory, skip\n\t\t}\n\t}\n\n\treturn workshops\n}\n\nexport async function getWorkshop(\n\tidOrName: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.find(\n\t\t(w) =>\n\t\t\tw.name.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.repoName.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.title.toLowerCase() === idOrName.toLowerCase(),\n\t)\n}\n\nexport async function workshopExists(repoName: string): Promise<boolean> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.some(\n\t\t(w) => w.repoName.toLowerCase() === repoName.toLowerCase(),\n\t)\n}\n\nexport async function getWorkshopByPath(\n\tworkshopPath: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\tconst resolvedPath = path.resolve(workshopPath)\n\treturn workshops.find((w) => path.resolve(w.path) === resolvedPath)\n}\n\n/**\n * Check for unpushed changes in a git repository\n * Returns info about unpushed commits across all branches\n */\nexport async function getUnpushedChanges(repoPath: string): Promise<{\n\thasUnpushed: boolean\n\tbranches: Array<{ name: string; unpushedCount: number }>\n\tuncommittedChanges: boolean\n\tsummary: string[]\n}> {\n\tconst { execSync } = await import('node:child_process')\n\n\tconst result = {\n\t\thasUnpushed: false,\n\t\tbranches: [] as Array<{ name: string; unpushedCount: number }>,\n\t\tuncommittedChanges: false,\n\t\tsummary: [] as string[],\n\t}\n\n\ttry {\n\t\t// Check if it's a git repository\n\t\texecSync('git rev-parse --git-dir', {\n\t\t\tcwd: repoPath,\n\t\t\tstdio: 'pipe',\n\t\t})\n\t} catch {\n\t\t// Not a git repository\n\t\treturn result\n\t}\n\n\ttry {\n\t\t// Check for uncommitted changes\n\t\tconst status = execSync('git status --porcelain', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tif (status) {\n\t\t\tresult.uncommittedChanges = true\n\t\t\tresult.hasUnpushed = true\n\t\t\tconst lines = status.split('\\n')\n\t\t\tconst modified = lines.filter(\n\t\t\t\t(l) => l.startsWith(' M') || l.startsWith('M '),\n\t\t\t).length\n\t\t\tconst added = lines.filter(\n\t\t\t\t(l) => l.startsWith('A ') || l.startsWith('??'),\n\t\t\t).length\n\t\t\tconst deleted = lines.filter(\n\t\t\t\t(l) => l.startsWith(' D') || l.startsWith('D '),\n\t\t\t).length\n\n\t\t\tconst parts = []\n\t\t\tif (modified > 0) parts.push(`${modified} modified`)\n\t\t\tif (added > 0) parts.push(`${added} untracked/added`)\n\t\t\tif (deleted > 0) parts.push(`${deleted} deleted`)\n\t\t\tif (parts.length > 0) {\n\t\t\t\tresult.summary.push(`Uncommitted changes: ${parts.join(', ')}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get all local branches\n\t\tconst branchOutput = execSync('git branch', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tconst branches = branchOutput\n\t\t\t.split('\\n')\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, '').trim())\n\t\t\t.filter(Boolean)\n\n\t\tfor (const branch of branches) {\n\t\t\ttry {\n\t\t\t\t// Check if branch has an upstream\n\t\t\t\tconst upstream = execSync(\n\t\t\t\t\t`git rev-parse --abbrev-ref ${branch}@{upstream}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\t// Count unpushed commits\n\t\t\t\tconst unpushedOutput = execSync(\n\t\t\t\t\t`git rev-list --count ${upstream}..${branch}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\tconst unpushedCount = parseInt(unpushedOutput, 10)\n\t\t\t\tif (unpushedCount > 0) {\n\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount })\n\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t`Branch \"${branch}\": ${unpushedCount} unpushed commit${unpushedCount > 1 ? 's' : ''}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Branch has no upstream, check if it has any commits not in any remote\n\t\t\t\ttry {\n\t\t\t\t\tconst allRemotes = execSync('git remote', {\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t}).trim()\n\n\t\t\t\t\tif (allRemotes) {\n\t\t\t\t\t\t// Branch exists but has no upstream tracking\n\t\t\t\t\t\tconst commitCount = execSync(`git rev-list --count ${branch}`, {\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\t}).trim()\n\n\t\t\t\t\t\tconst count = parseInt(commitCount, 10)\n\t\t\t\t\t\tif (count > 0) {\n\t\t\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount: count })\n\t\t\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t\t\t`Branch \"${branch}\": ${count} local commit${count > 1 ? 's' : ''} (no upstream)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors for individual branches\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Error checking git status, assume no unpushed changes\n\t}\n\n\treturn result\n}\n\n/**\n * Delete a workshop directory\n */\nexport async function deleteWorkshop(workshopPath: string): Promise<void> {\n\tawait fs.rm(workshopPath, { recursive: true, force: true })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epic-web/workshop-utils",
3
- "version": "6.47.0",
3
+ "version": "6.47.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },