@epic-web/workshop-utils 4.5.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/esm/apps.server.d.ts +7 -1
  2. package/dist/esm/apps.server.d.ts.map +1 -1
  3. package/dist/esm/apps.server.js +17 -7
  4. package/dist/esm/apps.server.js.map +1 -1
  5. package/dist/esm/cache.server.d.ts.map +1 -1
  6. package/dist/esm/cache.server.js +2 -3
  7. package/dist/esm/cache.server.js.map +1 -1
  8. package/dist/esm/codefile-mdx.server.d.ts.map +1 -1
  9. package/dist/esm/codefile-mdx.server.js +10 -11
  10. package/dist/esm/codefile-mdx.server.js.map +1 -1
  11. package/dist/esm/compile-mdx.server.d.ts.map +1 -1
  12. package/dist/esm/compile-mdx.server.js +6 -7
  13. package/dist/esm/compile-mdx.server.js.map +1 -1
  14. package/dist/esm/db.server.js +1 -1
  15. package/dist/esm/db.server.js.map +1 -1
  16. package/dist/esm/iframe-sync.d.ts.map +1 -1
  17. package/dist/esm/iframe-sync.js +0 -4
  18. package/dist/esm/iframe-sync.js.map +1 -1
  19. package/dist/esm/playwright.server.d.ts.map +1 -1
  20. package/dist/esm/playwright.server.js +9 -10
  21. package/dist/esm/playwright.server.js.map +1 -1
  22. package/dist/esm/process-manager.server.d.ts.map +1 -1
  23. package/dist/esm/process-manager.server.js +10 -10
  24. package/dist/esm/process-manager.server.js.map +1 -1
  25. package/dist/esm/test.d.ts.map +1 -1
  26. package/dist/esm/test.js +1 -2
  27. package/dist/esm/test.js.map +1 -1
  28. package/dist/esm/timing.server.d.ts.map +1 -1
  29. package/dist/esm/timing.server.js +2 -4
  30. package/dist/esm/timing.server.js.map +1 -1
  31. package/dist/esm/utils.server.d.ts.map +1 -1
  32. package/dist/esm/utils.server.js +0 -1
  33. package/dist/esm/utils.server.js.map +1 -1
  34. package/package.json +2 -2
@@ -1,16 +1,16 @@
1
- import { test, expect } from '@playwright/test';
1
+ import { expect, test } from '@playwright/test';
2
2
  import crossSpawn from 'cross-spawn';
3
3
  import z from 'zod';
4
4
  import { getApps, isProblemApp } from './apps.server.js';
5
5
  export async function getInBrowserTestPages() {
6
6
  const apps = (await getApps())
7
7
  .filter(isProblemApp)
8
- .filter(a => a.test.type === 'browser');
9
- const pages = apps.map(app => {
8
+ .filter((a) => a.test.type === 'browser');
9
+ const pages = apps.map((app) => {
10
10
  if (app.test.type !== 'browser')
11
11
  return null;
12
12
  const { pathname } = app.test;
13
- return app.test.testFiles.map(testFile => {
13
+ return app.test.testFiles.map((testFile) => {
14
14
  return {
15
15
  path: `${pathname}${testFile}`,
16
16
  testFile,
@@ -19,7 +19,7 @@ export async function getInBrowserTestPages() {
19
19
  });
20
20
  return pages.filter(Boolean).flat();
21
21
  }
22
- const sleep = (time) => new Promise(resolve => setTimeout(resolve, time));
22
+ const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
23
23
  async function waitFor(cb, { timeout = 1000, interval = 30 } = {}) {
24
24
  const timeEnd = Date.now() + timeout;
25
25
  let lastError = null;
@@ -50,12 +50,11 @@ export function setupInBrowserTests() {
50
50
  .array(z.object({ path: z.string() }))
51
51
  .parse(JSON.parse(result.stdout));
52
52
  for (const testPage of testPages) {
53
- // eslint-disable-next-line no-loop-func
54
53
  test(testPage.path, async ({ page }) => {
55
54
  const errors = [];
56
55
  const logs = [];
57
56
  const infos = [];
58
- page.on('console', message => {
57
+ page.on('console', (message) => {
59
58
  switch (message.type()) {
60
59
  case 'error': {
61
60
  errors.push(message.text());
@@ -76,14 +75,14 @@ export function setupInBrowserTests() {
76
75
  });
77
76
  await page.goto(testPage.path);
78
77
  await page.waitForLoadState();
79
- await waitFor(() => infos.find(info => info.includes('status: pending')), { timeout: 10_000 });
78
+ await waitFor(() => infos.find((info) => info.includes('status: pending')), { timeout: 10_000 });
80
79
  const result = await Promise.race([
81
- waitFor(() => logs.find(log => log.includes('status: pass')), {
80
+ waitFor(() => logs.find((log) => log.includes('status: pass')), {
82
81
  timeout: 10_000,
83
82
  }),
84
83
  waitFor(() => (errors.length > 0 ? errors : null), {
85
84
  timeout: 10_000,
86
- }).then(errors => {
85
+ }).then((errors) => {
87
86
  throw errors;
88
87
  }),
89
88
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"playwright.server.js","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect } from '@playwright/test'\nimport crossSpawn from 'cross-spawn'\nimport z from 'zod'\nimport { getApps, isProblemApp } from './apps.server.js'\n\nexport async function getInBrowserTestPages() {\n\tconst apps = (await getApps())\n\t\t.filter(isProblemApp)\n\t\t.filter(a => a.test.type === 'browser')\n\tconst pages = apps.map(app => {\n\t\tif (app.test.type !== 'browser') return null\n\t\tconst { pathname } = app.test\n\t\treturn app.test.testFiles.map(testFile => {\n\t\t\treturn {\n\t\t\t\tpath: `${pathname}${testFile}`,\n\t\t\t\ttestFile,\n\t\t\t}\n\t\t})\n\t})\n\treturn pages.filter(Boolean).flat()\n}\n\nconst sleep = (time: number) =>\n\tnew Promise(resolve => setTimeout(resolve, time))\n\nasync function waitFor<ReturnValue>(\n\tcb: () => ReturnValue | Promise<ReturnValue> | undefined | null,\n\t{ timeout = 1000, interval = 30 } = {},\n) {\n\tconst timeEnd = Date.now() + timeout\n\tlet lastError: unknown | null = null\n\twhile (Date.now() < timeEnd) {\n\t\ttry {\n\t\t\tconst result = await cb()\n\t\t\tif (result) return result\n\t\t} catch (error) {\n\t\t\tlastError = error\n\t\t}\n\t\tawait sleep(interval)\n\t}\n\tthrow lastError || new Error(`waitFor timed out after ${timeout}ms`)\n}\n\nexport function setupInBrowserTests() {\n\t// doing this because playwright needs the tests to be registered synchoronously\n\tconst code = `import('@epic-web/workshop-utils/playwright.server').then(({ getInBrowserTestPages }) => getInBrowserTestPages().then(r => console.log(JSON.stringify(r))))`\n\tconst result = crossSpawn.sync('node', ['--eval', code], {\n\t\tencoding: 'utf-8',\n\t})\n\tif (result.status !== 0) {\n\t\tconsole.error(result.output.join('\\n'))\n\t\tthrow new Error(\n\t\t\t`Failed to get in-browser test pages. Status: ${result.status}.`,\n\t\t)\n\t}\n\tconst testPages = z\n\t\t.array(z.object({ path: z.string() }))\n\t\t.parse(JSON.parse(result.stdout))\n\n\tfor (const testPage of testPages) {\n\t\t// eslint-disable-next-line no-loop-func\n\t\ttest(testPage.path, async ({ page }) => {\n\t\t\tconst errors: Array<string> = []\n\t\t\tconst logs: Array<string> = []\n\t\t\tconst infos: Array<string> = []\n\t\t\tpage.on('console', message => {\n\t\t\t\tswitch (message.type()) {\n\t\t\t\t\tcase 'error': {\n\t\t\t\t\t\terrors.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'log': {\n\t\t\t\t\t\tlogs.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'info': {\n\t\t\t\t\t\tinfos.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait page.goto(testPage.path)\n\t\t\tawait page.waitForLoadState()\n\t\t\tawait waitFor(\n\t\t\t\t() => infos.find(info => info.includes('status: pending')),\n\t\t\t\t{ timeout: 10_000 },\n\t\t\t)\n\t\t\tconst result = await Promise.race([\n\t\t\t\twaitFor(() => logs.find(log => log.includes('status: pass')), {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t}),\n\t\t\t\twaitFor(() => (errors.length > 0 ? errors : null), {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t}).then(errors => {\n\t\t\t\t\tthrow errors\n\t\t\t\t}),\n\t\t\t])\n\t\t\texpect(result).toContain('status: pass')\n\t\t})\n\t}\n}\n"]}
1
+ {"version":3,"file":"playwright.server.js","sourceRoot":"","sources":["../../src/playwright.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, test } from '@playwright/test'\nimport crossSpawn from 'cross-spawn'\nimport z from 'zod'\nimport { getApps, isProblemApp } from './apps.server.js'\n\nexport async function getInBrowserTestPages() {\n\tconst apps = (await getApps())\n\t\t.filter(isProblemApp)\n\t\t.filter((a) => a.test.type === 'browser')\n\tconst pages = apps.map((app) => {\n\t\tif (app.test.type !== 'browser') return null\n\t\tconst { pathname } = app.test\n\t\treturn app.test.testFiles.map((testFile) => {\n\t\t\treturn {\n\t\t\t\tpath: `${pathname}${testFile}`,\n\t\t\t\ttestFile,\n\t\t\t}\n\t\t})\n\t})\n\treturn pages.filter(Boolean).flat()\n}\n\nconst sleep = (time: number) =>\n\tnew Promise((resolve) => setTimeout(resolve, time))\n\nasync function waitFor<ReturnValue>(\n\tcb: () => ReturnValue | Promise<ReturnValue> | undefined | null,\n\t{ timeout = 1000, interval = 30 } = {},\n) {\n\tconst timeEnd = Date.now() + timeout\n\tlet lastError: unknown | null = null\n\twhile (Date.now() < timeEnd) {\n\t\ttry {\n\t\t\tconst result = await cb()\n\t\t\tif (result) return result\n\t\t} catch (error) {\n\t\t\tlastError = error\n\t\t}\n\t\tawait sleep(interval)\n\t}\n\tthrow lastError || new Error(`waitFor timed out after ${timeout}ms`)\n}\n\nexport function setupInBrowserTests() {\n\t// doing this because playwright needs the tests to be registered synchoronously\n\tconst code = `import('@epic-web/workshop-utils/playwright.server').then(({ getInBrowserTestPages }) => getInBrowserTestPages().then(r => console.log(JSON.stringify(r))))`\n\tconst result = crossSpawn.sync('node', ['--eval', code], {\n\t\tencoding: 'utf-8',\n\t})\n\tif (result.status !== 0) {\n\t\tconsole.error(result.output.join('\\n'))\n\t\tthrow new Error(\n\t\t\t`Failed to get in-browser test pages. Status: ${result.status}.`,\n\t\t)\n\t}\n\tconst testPages = z\n\t\t.array(z.object({ path: z.string() }))\n\t\t.parse(JSON.parse(result.stdout))\n\n\tfor (const testPage of testPages) {\n\t\ttest(testPage.path, async ({ page }) => {\n\t\t\tconst errors: Array<string> = []\n\t\t\tconst logs: Array<string> = []\n\t\t\tconst infos: Array<string> = []\n\t\t\tpage.on('console', (message) => {\n\t\t\t\tswitch (message.type()) {\n\t\t\t\t\tcase 'error': {\n\t\t\t\t\t\terrors.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'log': {\n\t\t\t\t\t\tlogs.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'info': {\n\t\t\t\t\t\tinfos.push(message.text())\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait page.goto(testPage.path)\n\t\t\tawait page.waitForLoadState()\n\t\t\tawait waitFor(\n\t\t\t\t() => infos.find((info) => info.includes('status: pending')),\n\t\t\t\t{ timeout: 10_000 },\n\t\t\t)\n\t\t\tconst result = await Promise.race([\n\t\t\t\twaitFor(() => logs.find((log) => log.includes('status: pass')), {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t}),\n\t\t\t\twaitFor(() => (errors.length > 0 ? errors : null), {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t}).then((errors) => {\n\t\t\t\t\tthrow errors\n\t\t\t\t}),\n\t\t\t])\n\t\t\texpect(result).toContain('status: pass')\n\t\t})\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.server.d.ts","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,eAAe,CAAA;AAIxD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,KAAK,aAAa,EAAgB,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAO3C,KAAK,eAAe,GAAG,GAAG,CACzB,MAAM,EACN;IACC,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;CACZ,CACD,CAAA;AAED,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACvB,OAAO,EAAE,aAAa,GAAG,IAAI,CAAA;IAC7B,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,KAAK,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AACrD,OAAO,CAAC,MAAM,CAAC;IACd,IAAI,uCAAuC,EAAE,UAAU,CACrD,OAAO,cAAc,CACrB,EACD,wCAAwC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAC5E;AAmCD,QAAA,MAAM,MAAM,mIAWF,CAAA;AAEV,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;GAoEvC;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;GAmDzC;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;UAuBvC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WASjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAUlD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,gCAExD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAE1D;AAED,wBAAgB,YAAY;;;EAE3B;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,iBAoB7C;AAID,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAInD;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAWnE"}
1
+ {"version":3,"file":"process-manager.server.d.ts","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":";AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAIxD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAO3C,KAAK,eAAe,GAAG,GAAG,CACzB,MAAM,EACN;IACC,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;CACZ,CACD,CAAA;AAED,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACvB,OAAO,EAAE,aAAa,GAAG,IAAI,CAAA;IAC7B,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,KAAK,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AACrD,OAAO,CAAC,MAAM,CAAC;IACd,IAAI,uCAAuC,EAAE,UAAU,CACrD,OAAO,cAAc,CACrB,EACD,wCAAwC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAC5E;AAmCD,QAAA,MAAM,MAAM,mIAWF,CAAA;AAEV,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;GAoEvC;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;;;;;GAmDzC;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG;;;;;;UAuBvC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WASjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAUlD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,gCAExD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAE1D;AAED,wBAAgB,YAAY;;;EAE3B;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,iBAoB7C;AAID,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAInD;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,iBAWnE"}
@@ -61,7 +61,7 @@ export async function runAppDev(app) {
61
61
  if (!(await isPortAvailable(portNumber))) {
62
62
  return { status: 'port-unavailable', running: false, portNumber };
63
63
  }
64
- const availableColors = colors.filter(color => Array.from(devProcesses.values()).every(p => p.color !== color));
64
+ const availableColors = colors.filter((color) => Array.from(devProcesses.values()).every((p) => p.color !== color));
65
65
  const color = availableColors[devProcesses.size % availableColors.length] ?? 'blue';
66
66
  const appProcess = spawn('npm', ['run', 'dev'], {
67
67
  cwd: app.fullPath,
@@ -83,7 +83,7 @@ export async function runAppDev(app) {
83
83
  console.log(data
84
84
  .toString('utf-8')
85
85
  .split('\n')
86
- .map(line => `${prefix} ${line}`)
86
+ .map((line) => `${prefix} ${line}`)
87
87
  .join('\n'));
88
88
  }
89
89
  appProcess.stdout.on('data', handleStdOutData);
@@ -91,12 +91,12 @@ export async function runAppDev(app) {
91
91
  console.error(data
92
92
  .toString('utf-8')
93
93
  .split('\n')
94
- .map(line => `${prefix} ${line}`)
94
+ .map((line) => `${prefix} ${line}`)
95
95
  .join('\n'));
96
96
  }
97
97
  appProcess.stderr.on('data', handleStdErrData);
98
98
  devProcesses.set(key, { color, process: appProcess, port: portNumber });
99
- appProcess.on('exit', code => {
99
+ appProcess.on('exit', (code) => {
100
100
  appProcess.stdout.off('data', handleStdOutData);
101
101
  appProcess.stderr.off('data', handleStdErrData);
102
102
  console.log(`${prefix} exited (${code})`);
@@ -144,7 +144,7 @@ export async function runAppTests(app) {
144
144
  });
145
145
  }
146
146
  testProcess.stderr?.on('data', handleStdErrData);
147
- void testProcess.on('exit', code => {
147
+ void testProcess.on('exit', (code) => {
148
148
  testProcess.stdout?.off('data', handleStdOutData);
149
149
  testProcess.stderr?.off('data', handleStdErrData);
150
150
  // don't delete the entry from the map so we can show the output at any time
@@ -170,7 +170,7 @@ export async function waitOnApp(app) {
170
170
  }
171
171
  catch (error) {
172
172
  lastError = error;
173
- await new Promise(resolve => setTimeout(resolve, retryInterval));
173
+ await new Promise((resolve) => setTimeout(resolve, retryInterval));
174
174
  }
175
175
  }
176
176
  return { status: 'error', error: getErrorMessage(lastError) };
@@ -178,7 +178,7 @@ export async function waitOnApp(app) {
178
178
  return null;
179
179
  }
180
180
  export function isPortAvailable(port) {
181
- return new Promise(resolve => {
181
+ return new Promise((resolve) => {
182
182
  const server = net.createServer();
183
183
  server.unref();
184
184
  server.on('error', () => resolve(false));
@@ -229,7 +229,7 @@ export async function closeProcess(key) {
229
229
  throw new Error('cannot close processes in deployed mode');
230
230
  const proc = devProcesses.get(key);
231
231
  if (proc) {
232
- const exitedPromise = new Promise(resolve => proc.process.on('exit', resolve));
232
+ const exitedPromise = new Promise((resolve) => proc.process.on('exit', resolve));
233
233
  if (process.platform === 'win32') {
234
234
  const { execa } = await import('execa');
235
235
  await execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/t']);
@@ -238,14 +238,14 @@ export async function closeProcess(key) {
238
238
  proc.process.kill();
239
239
  }
240
240
  await Promise.race([
241
- new Promise(resolve => setTimeout(resolve, 500)),
241
+ new Promise((resolve) => setTimeout(resolve, 500)),
242
242
  exitedPromise,
243
243
  ]);
244
244
  await stopPort(proc.port); // just in case 🤷‍♂️
245
245
  devProcesses.delete(key);
246
246
  }
247
247
  }
248
- const sleep = (t) => new Promise(resolve => setTimeout(resolve, t));
248
+ const sleep = (t) => new Promise((resolve) => setTimeout(resolve, t));
249
249
  export async function stopPort(port) {
250
250
  if (isDeployed)
251
251
  throw new Error('cannot stop ports in deployed mode');
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.server.js","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn } from 'child_process'\nimport net from 'node:net'\nimport { remember } from '@epic-web/remember'\nimport chalk from 'chalk'\nimport closeWithGrace from 'close-with-grace'\nimport { type ResultPromise, execaCommand } from 'execa'\nimport fkill from 'fkill'\nimport { type App } from './apps.server.js'\nimport { getErrorMessage } from './utils.js'\n\nconst isDeployed =\n\tprocess.env.EPICSHOP_DEPLOYED === 'true' ||\n\tprocess.env.EPICSHOP_DEPLOYED === '1'\n\ntype DevProcessesMap = Map<\n\tstring,\n\t{\n\t\tcolor: (typeof colors)[number]\n\t\tprocess: ChildProcess\n\t\tport: number\n\t}\n>\n\ntype OutputLine = {\n\ttype: 'stdout' | 'stderr'\n\tcontent: string\n\ttimestamp: number\n}\n\ntype TestProcessEntry = {\n\tprocess: ResultPromise | null\n\toutput: Array<OutputLine>\n\texitCode?: number | null\n}\n\ntype TestProcessesMap = Map<string, TestProcessEntry>\ndeclare global {\n\tvar __process_dev_close_with_grace_return__: ReturnType<\n\t\t\ttypeof closeWithGrace\n\t\t>,\n\t\t__process_test_close_with_grace_return__: ReturnType<typeof closeWithGrace>\n}\n\nconst devProcesses = remember('dev_processes', getDevProcessesMap)\nconst testProcesses = remember('test_processes', getTestProcessesMap)\n\nfunction getDevProcessesMap() {\n\tconst procs: DevProcessesMap = new Map()\n\n\tglobal.__process_dev_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_dev_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [name, proc] of procs.entries()) {\n\t\t\tconsole.log('closing', name)\n\t\t\tproc.process.kill()\n\t\t}\n\t})\n\treturn procs\n}\n\nfunction getTestProcessesMap() {\n\tconst procs: TestProcessesMap = new Map()\n\n\tglobal.__process_test_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_test_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [id, proc] of procs.entries()) {\n\t\t\tif (proc.process) {\n\t\t\t\tconsole.log('closing', id)\n\t\t\t\tproc.process.kill()\n\t\t\t}\n\t\t}\n\t})\n\treturn procs\n}\n\nconst colors = [\n\t'blue',\n\t'green',\n\t'yellow',\n\t'red',\n\t'magenta',\n\t'redBright',\n\t'greenBright',\n\t'yellowBright',\n\t'blueBright',\n\t'magentaBright',\n] as const\n\nexport async function runAppDev(app: App) {\n\tif (isDeployed) throw new Error('cannot run apps in deployed mode')\n\tconst key = app.name\n\t// if the app is already running, don't start it again\n\tif (devProcesses.has(key)) {\n\t\treturn { status: 'process-running', running: true } as const\n\t}\n\n\tif (app.dev.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-server' } as const\n\t}\n\n\tconst { portNumber } = app.dev\n\tif (!(await isPortAvailable(portNumber))) {\n\t\treturn { status: 'port-unavailable', running: false, portNumber } as const\n\t}\n\tconst availableColors = colors.filter(color =>\n\t\tArray.from(devProcesses.values()).every(p => p.color !== color),\n\t)\n\tconst color =\n\t\tavailableColors[devProcesses.size % availableColors.length] ?? 'blue'\n\tconst appProcess = spawn('npm', ['run', 'dev'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: String(portNumber),\n\t\t\tAPP_SERVER_PORT: String(portNumber),\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst prefix = chalk[color](\n\t\t`[${app.name.replace(/^exercises\\./, '')}:${portNumber}]`,\n\t)\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map(line => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map(line => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stderr.on('data', handleStdErrData)\n\tdevProcesses.set(key, { color, process: appProcess, port: portNumber })\n\tappProcess.on('exit', code => {\n\t\tappProcess.stdout.off('data', handleStdOutData)\n\t\tappProcess.stderr.off('data', handleStdErrData)\n\t\tconsole.log(`${prefix} exited (${code})`)\n\t\tdevProcesses.delete(key)\n\t})\n\n\treturn { status: 'process-started', running: true } as const\n}\n\nexport async function runAppTests(app: App) {\n\tif (isDeployed) throw new Error('cannot run tests in deployed mode')\n\tconst key = app.name\n\n\tif (app.test.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-test' } as const\n\t}\n\n\tconst testProcess = execaCommand(app.test.script, {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: app.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\tAPP_SERVER_PORT:\n\t\t\t\tapp.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst output: Array<OutputLine> = []\n\tconst entry: TestProcessEntry = { process: testProcess, output }\n\tfunction handleStdOutData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stdout',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stdout?.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stderr',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stderr?.on('data', handleStdErrData)\n\tvoid testProcess.on('exit', code => {\n\t\ttestProcess.stdout?.off('data', handleStdOutData)\n\t\ttestProcess.stderr?.off('data', handleStdErrData)\n\t\t// don't delete the entry from the map so we can show the output at any time\n\t\tentry.process = null\n\t\tentry.exitCode = code\n\t})\n\ttestProcesses.set(key, entry)\n\treturn testProcess\n}\n\nexport async function waitOnApp(app: App) {\n\tif (app.dev.type === 'script') {\n\t\tconst startTime = Date.now()\n\n\t\tconst retryInterval = 100\n\t\tconst timeout = 20_000\n\t\tlet lastError: unknown\n\t\twhile (Date.now() - startTime < timeout) {\n\t\t\ttry {\n\t\t\t\tawait fetch(`http://localhost:${app.dev.portNumber}`, {\n\t\t\t\t\tmethod: 'HEAD',\n\t\t\t\t\theaders: { Accept: '*/*' },\n\t\t\t\t})\n\t\t\t\treturn { status: 'success' } as const\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tawait new Promise(resolve => setTimeout(resolve, retryInterval))\n\t\t\t}\n\t\t}\n\n\t\treturn { status: 'error', error: getErrorMessage(lastError) } as const\n\t}\n\treturn null\n}\n\nexport function isPortAvailable(port: number | string): Promise<boolean> {\n\treturn new Promise(resolve => {\n\t\tconst server = net.createServer()\n\t\tserver.unref()\n\t\tserver.on('error', () => resolve(false))\n\n\t\tserver.listen(Number(port), () => {\n\t\t\tserver.close(() => {\n\t\t\t\tresolve(true)\n\t\t\t})\n\t\t})\n\t})\n}\n\nexport function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess) return false\n\t\tdevProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function isTestRunning(app: { name: string }) {\n\ttry {\n\t\tconst testProcess = testProcesses.get(app.name)\n\t\tif (!testProcess) return false\n\t\tif (testProcess.process === null) return false\n\t\ttestProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function getTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.get(app.name)\n}\n\nexport function clearTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.delete(app.name)\n}\n\nexport function getProcesses() {\n\treturn { devProcesses, testProcesses }\n}\n\nexport async function closeProcess(key: string) {\n\tif (isDeployed) throw new Error('cannot close processes in deployed mode')\n\tconst proc = devProcesses.get(key)\n\tif (proc) {\n\t\tconst exitedPromise = new Promise(resolve =>\n\t\t\tproc.process.on('exit', resolve),\n\t\t)\n\t\tif (process.platform === 'win32') {\n\t\t\tconst { execa } = await import('execa')\n\t\t\tawait execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/t'])\n\t\t} else {\n\t\t\tproc.process.kill()\n\t\t}\n\t\tawait Promise.race([\n\t\t\tnew Promise(resolve => setTimeout(resolve, 500)),\n\t\t\texitedPromise,\n\t\t])\n\t\tawait stopPort(proc.port) // just in case 🤷‍♂️\n\t\tdevProcesses.delete(key)\n\t}\n}\n\nconst sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t))\n\nexport async function stopPort(port: string | number) {\n\tif (isDeployed) throw new Error('cannot stop ports in deployed mode')\n\tawait fkill(`:${port}`, { force: true, silent: true })\n\tawait waitForPortToBeAvailable(port)\n}\n\nexport async function waitForPortToBeAvailable(port: string | number) {\n\t// wait for the port to become available again\n\tconst timeout = Date.now() + 10_000\n\tlet portAvailable = false\n\tdo {\n\t\tportAvailable = await isPortAvailable(port)\n\t\tawait sleep(100)\n\t} while (!portAvailable && Date.now() < timeout)\n\tif (!portAvailable) {\n\t\tconsole.error('Timed out waiting for the port to become available')\n\t}\n}\n"]}
1
+ {"version":3,"file":"process-manager.server.js","sourceRoot":"","sources":["../../src/process-manager.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcess } from 'child_process'\nimport net from 'node:net'\nimport { remember } from '@epic-web/remember'\nimport chalk from 'chalk'\nimport closeWithGrace from 'close-with-grace'\nimport { execaCommand, type ResultPromise } from 'execa'\nimport fkill from 'fkill'\nimport { type App } from './apps.server.js'\nimport { getErrorMessage } from './utils.js'\n\nconst isDeployed =\n\tprocess.env.EPICSHOP_DEPLOYED === 'true' ||\n\tprocess.env.EPICSHOP_DEPLOYED === '1'\n\ntype DevProcessesMap = Map<\n\tstring,\n\t{\n\t\tcolor: (typeof colors)[number]\n\t\tprocess: ChildProcess\n\t\tport: number\n\t}\n>\n\ntype OutputLine = {\n\ttype: 'stdout' | 'stderr'\n\tcontent: string\n\ttimestamp: number\n}\n\ntype TestProcessEntry = {\n\tprocess: ResultPromise | null\n\toutput: Array<OutputLine>\n\texitCode?: number | null\n}\n\ntype TestProcessesMap = Map<string, TestProcessEntry>\ndeclare global {\n\tvar __process_dev_close_with_grace_return__: ReturnType<\n\t\t\ttypeof closeWithGrace\n\t\t>,\n\t\t__process_test_close_with_grace_return__: ReturnType<typeof closeWithGrace>\n}\n\nconst devProcesses = remember('dev_processes', getDevProcessesMap)\nconst testProcesses = remember('test_processes', getTestProcessesMap)\n\nfunction getDevProcessesMap() {\n\tconst procs: DevProcessesMap = new Map()\n\n\tglobal.__process_dev_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_dev_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [name, proc] of procs.entries()) {\n\t\t\tconsole.log('closing', name)\n\t\t\tproc.process.kill()\n\t\t}\n\t})\n\treturn procs\n}\n\nfunction getTestProcessesMap() {\n\tconst procs: TestProcessesMap = new Map()\n\n\tglobal.__process_test_close_with_grace_return__?.uninstall()\n\n\tglobal.__process_test_close_with_grace_return__ = closeWithGrace(async () => {\n\t\tfor (const [id, proc] of procs.entries()) {\n\t\t\tif (proc.process) {\n\t\t\t\tconsole.log('closing', id)\n\t\t\t\tproc.process.kill()\n\t\t\t}\n\t\t}\n\t})\n\treturn procs\n}\n\nconst colors = [\n\t'blue',\n\t'green',\n\t'yellow',\n\t'red',\n\t'magenta',\n\t'redBright',\n\t'greenBright',\n\t'yellowBright',\n\t'blueBright',\n\t'magentaBright',\n] as const\n\nexport async function runAppDev(app: App) {\n\tif (isDeployed) throw new Error('cannot run apps in deployed mode')\n\tconst key = app.name\n\t// if the app is already running, don't start it again\n\tif (devProcesses.has(key)) {\n\t\treturn { status: 'process-running', running: true } as const\n\t}\n\n\tif (app.dev.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-server' } as const\n\t}\n\n\tconst { portNumber } = app.dev\n\tif (!(await isPortAvailable(portNumber))) {\n\t\treturn { status: 'port-unavailable', running: false, portNumber } as const\n\t}\n\tconst availableColors = colors.filter((color) =>\n\t\tArray.from(devProcesses.values()).every((p) => p.color !== color),\n\t)\n\tconst color =\n\t\tavailableColors[devProcesses.size % availableColors.length] ?? 'blue'\n\tconst appProcess = spawn('npm', ['run', 'dev'], {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: String(portNumber),\n\t\t\tAPP_SERVER_PORT: String(portNumber),\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst prefix = chalk[color](\n\t\t`[${app.name.replace(/^exercises\\./, '')}:${portNumber}]`,\n\t)\n\tfunction handleStdOutData(data: Buffer) {\n\t\tconsole.log(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stdout.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\tconsole.error(\n\t\t\tdata\n\t\t\t\t.toString('utf-8')\n\t\t\t\t.split('\\n')\n\t\t\t\t.map((line) => `${prefix} ${line}`)\n\t\t\t\t.join('\\n'),\n\t\t)\n\t}\n\tappProcess.stderr.on('data', handleStdErrData)\n\tdevProcesses.set(key, { color, process: appProcess, port: portNumber })\n\tappProcess.on('exit', (code) => {\n\t\tappProcess.stdout.off('data', handleStdOutData)\n\t\tappProcess.stderr.off('data', handleStdErrData)\n\t\tconsole.log(`${prefix} exited (${code})`)\n\t\tdevProcesses.delete(key)\n\t})\n\n\treturn { status: 'process-started', running: true } as const\n}\n\nexport async function runAppTests(app: App) {\n\tif (isDeployed) throw new Error('cannot run tests in deployed mode')\n\tconst key = app.name\n\n\tif (app.test.type !== 'script') {\n\t\treturn { status: 'error', error: 'no-test' } as const\n\t}\n\n\tconst testProcess = execaCommand(app.test.script, {\n\t\tcwd: app.fullPath,\n\t\tshell: true,\n\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t// TODO: support specifying the env\n\t\t\tNODE_ENV: 'development',\n\t\t\t// TODO: support specifying the port\n\t\t\tPORT: app.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\tAPP_SERVER_PORT:\n\t\t\t\tapp.dev.type === 'script' ? String(app.dev.portNumber) : undefined,\n\t\t\t// let it pick a random port...\n\t\t\tREMIX_DEV_SERVER_WS_PORT: '',\n\t\t},\n\t})\n\tconst output: Array<OutputLine> = []\n\tconst entry: TestProcessEntry = { process: testProcess, output }\n\tfunction handleStdOutData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stdout',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stdout?.on('data', handleStdOutData)\n\tfunction handleStdErrData(data: Buffer) {\n\t\toutput.push({\n\t\t\ttype: 'stderr',\n\t\t\tcontent: data.toString('utf-8'),\n\t\t\ttimestamp: Date.now(),\n\t\t})\n\t}\n\ttestProcess.stderr?.on('data', handleStdErrData)\n\tvoid testProcess.on('exit', (code) => {\n\t\ttestProcess.stdout?.off('data', handleStdOutData)\n\t\ttestProcess.stderr?.off('data', handleStdErrData)\n\t\t// don't delete the entry from the map so we can show the output at any time\n\t\tentry.process = null\n\t\tentry.exitCode = code\n\t})\n\ttestProcesses.set(key, entry)\n\treturn testProcess\n}\n\nexport async function waitOnApp(app: App) {\n\tif (app.dev.type === 'script') {\n\t\tconst startTime = Date.now()\n\n\t\tconst retryInterval = 100\n\t\tconst timeout = 20_000\n\t\tlet lastError: unknown\n\t\twhile (Date.now() - startTime < timeout) {\n\t\t\ttry {\n\t\t\t\tawait fetch(`http://localhost:${app.dev.portNumber}`, {\n\t\t\t\t\tmethod: 'HEAD',\n\t\t\t\t\theaders: { Accept: '*/*' },\n\t\t\t\t})\n\t\t\t\treturn { status: 'success' } as const\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, retryInterval))\n\t\t\t}\n\t\t}\n\n\t\treturn { status: 'error', error: getErrorMessage(lastError) } as const\n\t}\n\treturn null\n}\n\nexport function isPortAvailable(port: number | string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = net.createServer()\n\t\tserver.unref()\n\t\tserver.on('error', () => resolve(false))\n\n\t\tserver.listen(Number(port), () => {\n\t\t\tserver.close(() => {\n\t\t\t\tresolve(true)\n\t\t\t})\n\t\t})\n\t})\n}\n\nexport function isAppRunning(app: { name: string }) {\n\ttry {\n\t\tconst devProcess = devProcesses.get(app.name)\n\t\tif (!devProcess) return false\n\t\tdevProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function isTestRunning(app: { name: string }) {\n\ttry {\n\t\tconst testProcess = testProcesses.get(app.name)\n\t\tif (!testProcess) return false\n\t\tif (testProcess.process === null) return false\n\t\ttestProcess.process.kill(0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function getTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.get(app.name)\n}\n\nexport function clearTestProcessEntry(app: { name: string }) {\n\treturn testProcesses.delete(app.name)\n}\n\nexport function getProcesses() {\n\treturn { devProcesses, testProcesses }\n}\n\nexport async function closeProcess(key: string) {\n\tif (isDeployed) throw new Error('cannot close processes in deployed mode')\n\tconst proc = devProcesses.get(key)\n\tif (proc) {\n\t\tconst exitedPromise = new Promise((resolve) =>\n\t\t\tproc.process.on('exit', resolve),\n\t\t)\n\t\tif (process.platform === 'win32') {\n\t\t\tconst { execa } = await import('execa')\n\t\t\tawait execa('taskkill', ['/pid', String(proc.process.pid), '/f', '/t'])\n\t\t} else {\n\t\t\tproc.process.kill()\n\t\t}\n\t\tawait Promise.race([\n\t\t\tnew Promise((resolve) => setTimeout(resolve, 500)),\n\t\t\texitedPromise,\n\t\t])\n\t\tawait stopPort(proc.port) // just in case 🤷‍♂️\n\t\tdevProcesses.delete(key)\n\t}\n}\n\nconst sleep = (t: number) => new Promise((resolve) => setTimeout(resolve, t))\n\nexport async function stopPort(port: string | number) {\n\tif (isDeployed) throw new Error('cannot stop ports in deployed mode')\n\tawait fkill(`:${port}`, { force: true, silent: true })\n\tawait waitForPortToBeAvailable(port)\n}\n\nexport async function waitForPortToBeAvailable(port: string | number) {\n\t// wait for the port to become available again\n\tconst timeout = Date.now() + 10_000\n\tlet portAvailable = false\n\tdo {\n\t\tportAvailable = await isPortAvailable(port)\n\t\tawait sleep(100)\n\t} while (!portAvailable && Date.now() < timeout)\n\tif (!portAvailable) {\n\t\tconsole.error('Timed out waiting for the port to become available')\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":";AAWA,eAAO,MAAQ,MAAM,mBAAS,CAAA;AAY9B,wBAAsB,QAAQ,CAAC,WAAW,EACzC,KAAK,EACF,MAAM,GACN,CAAC,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC,EAC1E,GAAG,EAAE,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GACrD,OAAO,CAAC,WAAW,CAAC,CA+BtB"}
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":";AAWA,eAAO,MAAQ,MAAM,mBAAS,CAAA;AAW9B,wBAAsB,QAAQ,CAAC,WAAW,EACzC,KAAK,EACF,MAAM,GACN,CAAC,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC,EAC1E,GAAG,EAAE,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GACrD,OAAO,CAAC,WAAW,CAAC,CA+BtB"}
package/dist/esm/test.js CHANGED
@@ -4,14 +4,13 @@ import chaiDOM from 'chai-dom';
4
4
  chai.use(chaiDOM);
5
5
  // in the browser logging out the element is not necessary
6
6
  configure({
7
- getElementError: message => new Error(message ?? 'Unknown error'),
7
+ getElementError: (message) => new Error(message ?? 'Unknown error'),
8
8
  });
9
9
  export const { expect } = chai;
10
10
  function isError(maybeError) {
11
11
  return (maybeError &&
12
12
  typeof maybeError === 'object' &&
13
13
  'message' in maybeError &&
14
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
15
14
  typeof maybeError.message === 'string');
16
15
  }
17
16
  export async function testStep(title, get) {
@@ -1 +1 @@
1
- {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,OAAO,MAAM,UAAU,CAAA;AAE9B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEjB,0DAA0D;AAC1D,SAAS,CAAC;IACT,eAAe,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,eAAe,CAAC;CACjE,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;AAE9B,SAAS,OAAO,CAAC,UAAe;IAC/B,OAAO,CACN,UAAU;QACV,OAAO,UAAU,KAAK,QAAQ;QAC9B,SAAS,IAAI,UAAU;QACvB,sEAAsE;QACtE,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,CACtC,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAE0E,EAC1E,GAAuD;IAEvD,IAAI,WAAW,CAAA;IACf,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAA;QAC1B,MAAM,WAAW,GAChB,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE,CAAC,CAAA;QAChC,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,MAAM,CAAC,WAAW,CACxB;gBACC,IAAI,EAAE,2BAA2B;gBACjC,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,EACD,GAAG,CACH,CAAA;QACF,CAAC;QACD,OAAO,MAAM,CAAA;IACd,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACrB,WAAW,GAAG,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC;QACjC,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;IAC7E,MAAM,WAAW,GAChB,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACrE,KAAK,CAAC,OAAO,GAAG,GAAG,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IAC9E,MAAM,KAAK,CAAA;AACZ,CAAC","sourcesContent":["import { configure } from '@testing-library/dom'\nimport * as chai from 'chai'\nimport chaiDOM from 'chai-dom'\n\nchai.use(chaiDOM)\n\n// in the browser logging out the element is not necessary\nconfigure({\n\tgetElementError: message => new Error(message ?? 'Unknown error'),\n})\n\nexport const { expect } = chai\n\nfunction isError(maybeError: any): maybeError is Error {\n\treturn (\n\t\tmaybeError &&\n\t\ttypeof maybeError === 'object' &&\n\t\t'message' in maybeError &&\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\ttypeof maybeError.message === 'string'\n\t)\n}\n\nexport async function testStep<ReturnValue>(\n\ttitle:\n\t\t| string\n\t\t| ((result: { type: 'fail'; error: Error } | { type: 'pass' }) => string),\n\tget: (() => ReturnValue) | (() => Promise<ReturnValue>),\n): Promise<ReturnValue> {\n\tlet caughtError\n\ttry {\n\t\tconst result = await get()\n\t\tconst titleString =\n\t\t\ttypeof title === 'function' ? title({ type: 'pass' }) : title\n\t\tif (window.parent === window) {\n\t\t\tconsole.log(`✅ ${titleString}`)\n\t\t} else {\n\t\t\twindow.parent.postMessage(\n\t\t\t\t{\n\t\t\t\t\ttype: 'epicshop:test-step-update',\n\t\t\t\t\tstatus: 'pass',\n\t\t\t\t\ttitle: titleString,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t\t'*',\n\t\t\t)\n\t\t}\n\t\treturn result\n\t} catch (e: unknown) {\n\t\tcaughtError = e\n\t}\n\n\tconst error = isError(caughtError)\n\t\t? caughtError\n\t\t: new Error(typeof caughtError === 'string' ? caughtError : 'Unknown error')\n\tconst titleString =\n\t\ttypeof title === 'function' ? title({ type: 'fail', error }) : title\n\terror.message = `${titleString}${error.message ? `\\n\\n${error.message}` : ''}`\n\tthrow error\n}\n"]}
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,OAAO,MAAM,UAAU,CAAA;AAE9B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEjB,0DAA0D;AAC1D,SAAS,CAAC;IACT,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,eAAe,CAAC;CACnE,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;AAE9B,SAAS,OAAO,CAAC,UAAe;IAC/B,OAAO,CACN,UAAU;QACV,OAAO,UAAU,KAAK,QAAQ;QAC9B,SAAS,IAAI,UAAU;QACvB,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,CACtC,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAE0E,EAC1E,GAAuD;IAEvD,IAAI,WAAW,CAAA;IACf,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAA;QAC1B,MAAM,WAAW,GAChB,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE,CAAC,CAAA;QAChC,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,MAAM,CAAC,WAAW,CACxB;gBACC,IAAI,EAAE,2BAA2B;gBACjC,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,EACD,GAAG,CACH,CAAA;QACF,CAAC;QACD,OAAO,MAAM,CAAA;IACd,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACrB,WAAW,GAAG,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC;QACjC,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;IAC7E,MAAM,WAAW,GAChB,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACrE,KAAK,CAAC,OAAO,GAAG,GAAG,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IAC9E,MAAM,KAAK,CAAA;AACZ,CAAC","sourcesContent":["import { configure } from '@testing-library/dom'\nimport * as chai from 'chai'\nimport chaiDOM from 'chai-dom'\n\nchai.use(chaiDOM)\n\n// in the browser logging out the element is not necessary\nconfigure({\n\tgetElementError: (message) => new Error(message ?? 'Unknown error'),\n})\n\nexport const { expect } = chai\n\nfunction isError(maybeError: any): maybeError is Error {\n\treturn (\n\t\tmaybeError &&\n\t\ttypeof maybeError === 'object' &&\n\t\t'message' in maybeError &&\n\t\ttypeof maybeError.message === 'string'\n\t)\n}\n\nexport async function testStep<ReturnValue>(\n\ttitle:\n\t\t| string\n\t\t| ((result: { type: 'fail'; error: Error } | { type: 'pass' }) => string),\n\tget: (() => ReturnValue) | (() => Promise<ReturnValue>),\n): Promise<ReturnValue> {\n\tlet caughtError\n\ttry {\n\t\tconst result = await get()\n\t\tconst titleString =\n\t\t\ttypeof title === 'function' ? title({ type: 'pass' }) : title\n\t\tif (window.parent === window) {\n\t\t\tconsole.log(`✅ ${titleString}`)\n\t\t} else {\n\t\t\twindow.parent.postMessage(\n\t\t\t\t{\n\t\t\t\t\ttype: 'epicshop:test-step-update',\n\t\t\t\t\tstatus: 'pass',\n\t\t\t\t\ttitle: titleString,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t\t'*',\n\t\t\t)\n\t\t}\n\t\treturn result\n\t} catch (e: unknown) {\n\t\tcaughtError = e\n\t}\n\n\tconst error = isError(caughtError)\n\t\t? caughtError\n\t\t: new Error(typeof caughtError === 'string' ? caughtError : 'Unknown error')\n\tconst titleString =\n\t\ttypeof title === 'function' ? title({ type: 'fail', error }) : title\n\terror.message = `${titleString}${error.message ? `\\n\\n${error.message}` : ''}`\n\tthrow error\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"timing.server.d.ts","sourceRoot":"","sources":["../../src/timing.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,MAAM,MAAM,OAAO,GAAG,MAAM,CAC3B,MAAM,EACN,KAAK,CACJ;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,CACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CACjC,CACD,CACD,CAAA;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,WAWtD;AAkBD,wBAAsB,IAAI,CAAC,UAAU,EACpC,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,EAClE,EACC,IAAI,EACJ,IAAI,EACJ,OAAO,GACP,EAAE;IACF,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,GACC,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,OAAO,UAuBpD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,UAIxE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAC5C,OAAO,CAAC,EAAE,OAAO,GACf,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CA4BnC"}
1
+ {"version":3,"file":"timing.server.d.ts","sourceRoot":"","sources":["../../src/timing.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,MAAM,MAAM,OAAO,GAAG,MAAM,CAC3B,MAAM,EACN,KAAK,CACJ;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,CACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CACjC,CACD,CACD,CAAA;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,WAWtD;AAgBD,wBAAsB,IAAI,CAAC,UAAU,EACpC,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,EAClE,EACC,IAAI,EACJ,IAAI,EACJ,OAAO,GACP,EAAE;IACF,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,GACC,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,OAAO,UAuBpD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,UAIxE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAC5C,OAAO,CAAC,EAAE,OAAO,GACf,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CA4BnC"}
@@ -15,9 +15,7 @@ function createTimer(type, desc) {
15
15
  return {
16
16
  end(timings) {
17
17
  let timingType = timings[type];
18
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
19
18
  if (!timingType) {
20
- // eslint-disable-next-line no-multi-assign
21
19
  timingType = timings[type] = [];
22
20
  }
23
21
  timingType.push({ desc, time: performance.now() - start });
@@ -45,7 +43,7 @@ export function getServerTimeHeader(timings) {
45
43
  }, 0)
46
44
  .toFixed(1);
47
45
  const desc = timingInfos
48
- .map(t => t.desc)
46
+ .map((t) => t.desc)
49
47
  .filter(Boolean)
50
48
  .join(' & ');
51
49
  return [
@@ -69,7 +67,7 @@ export function cachifiedTimingReporter(timings) {
69
67
  return ({ key }) => {
70
68
  const cacheRetrievalTimer = createTimer(`cache:${key}`, `${key} cache retrieval`);
71
69
  let getFreshValueTimer;
72
- return event => {
70
+ return (event) => {
73
71
  switch (event.name) {
74
72
  case 'getFreshValueStart':
75
73
  getFreshValueTimer = createTimer(`getFreshValue:${key}`, `request forced to wait for a fresh ${key} value`);
@@ -1 +1 @@
1
- {"version":3,"file":"timing.server.js","sourceRoot":"","sources":["../../src/timing.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CreateReporter } from '@epic-web/cachified'\n\nexport type Timings = Record<\n\tstring,\n\tArray<\n\t\t{ desc?: string } & (\n\t\t\t| { time: number; start?: never }\n\t\t\t| { time?: never; start: number }\n\t\t)\n\t>\n>\n\nexport function makeTimings(type: string, desc?: string) {\n\tconst timings: Timings = {\n\t\t[type]: [{ desc, start: performance.now() }],\n\t}\n\tObject.defineProperty(timings, 'toString', {\n\t\tvalue() {\n\t\t\treturn getServerTimeHeader(timings)\n\t\t},\n\t\tenumerable: false,\n\t})\n\treturn timings\n}\n\nfunction createTimer(type: string, desc?: string) {\n\tconst start = performance.now()\n\treturn {\n\t\tend(timings: Timings) {\n\t\t\tlet timingType = timings[type]\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\t\t\tif (!timingType) {\n\t\t\t\t// eslint-disable-next-line no-multi-assign\n\t\t\t\ttimingType = timings[type] = []\n\t\t\t}\n\t\t\ttimingType.push({ desc, time: performance.now() - start })\n\t\t},\n\t}\n}\n\nexport async function time<ReturnType>(\n\tfn: Promise<ReturnType> | (() => ReturnType | Promise<ReturnType>),\n\t{\n\t\ttype,\n\t\tdesc,\n\t\ttimings,\n\t}: {\n\t\ttype: string\n\t\tdesc?: string\n\t\ttimings?: Timings\n\t},\n): Promise<ReturnType> {\n\tconst timer = createTimer(type, desc)\n\tconst promise = typeof fn === 'function' ? fn() : fn\n\tif (!timings) return promise\n\n\tconst result = await promise\n\n\ttimer.end(timings)\n\treturn result\n}\n\nexport function getServerTimeHeader(timings?: Timings) {\n\tif (!timings) return ''\n\treturn Object.entries(timings)\n\t\t.map(([key, timingInfos]) => {\n\t\t\tconst dur = timingInfos\n\t\t\t\t.reduce((acc, timingInfo) => {\n\t\t\t\t\tconst time = timingInfo.time ?? performance.now() - timingInfo.start\n\t\t\t\t\treturn acc + time\n\t\t\t\t}, 0)\n\t\t\t\t.toFixed(1)\n\t\t\tconst desc = timingInfos\n\t\t\t\t.map(t => t.desc)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(' & ')\n\t\t\treturn [\n\t\t\t\tkey.replaceAll(/(:| |@|=|;|,|\\/|\\\\)/g, '_'),\n\t\t\t\tdesc ? `desc=${JSON.stringify(desc)}` : null,\n\t\t\t\t`dur=${dur}`,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(';')\n\t\t})\n\t\t.join(',')\n}\n\nexport function combineServerTimings(headers1: Headers, headers2: Headers) {\n\tconst newHeaders = new Headers(headers1)\n\tnewHeaders.append('Server-Timing', headers2.get('Server-Timing') ?? '')\n\treturn newHeaders.get('Server-Timing') ?? ''\n}\n\nexport function cachifiedTimingReporter<Value>(\n\ttimings?: Timings,\n): undefined | CreateReporter<Value> {\n\tif (!timings) return\n\n\treturn ({ key }) => {\n\t\tconst cacheRetrievalTimer = createTimer(\n\t\t\t`cache:${key}`,\n\t\t\t`${key} cache retrieval`,\n\t\t)\n\t\tlet getFreshValueTimer: ReturnType<typeof createTimer> | undefined\n\t\treturn event => {\n\t\t\tswitch (event.name) {\n\t\t\t\tcase 'getFreshValueStart':\n\t\t\t\t\tgetFreshValueTimer = createTimer(\n\t\t\t\t\t\t`getFreshValue:${key}`,\n\t\t\t\t\t\t`request forced to wait for a fresh ${key} value`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'getFreshValueSuccess':\n\t\t\t\t\tgetFreshValueTimer?.end(timings)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'done':\n\t\t\t\t\tcacheRetrievalTimer.end(timings)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"timing.server.js","sourceRoot":"","sources":["../../src/timing.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CreateReporter } from '@epic-web/cachified'\n\nexport type Timings = Record<\n\tstring,\n\tArray<\n\t\t{ desc?: string } & (\n\t\t\t| { time: number; start?: never }\n\t\t\t| { time?: never; start: number }\n\t\t)\n\t>\n>\n\nexport function makeTimings(type: string, desc?: string) {\n\tconst timings: Timings = {\n\t\t[type]: [{ desc, start: performance.now() }],\n\t}\n\tObject.defineProperty(timings, 'toString', {\n\t\tvalue() {\n\t\t\treturn getServerTimeHeader(timings)\n\t\t},\n\t\tenumerable: false,\n\t})\n\treturn timings\n}\n\nfunction createTimer(type: string, desc?: string) {\n\tconst start = performance.now()\n\treturn {\n\t\tend(timings: Timings) {\n\t\t\tlet timingType = timings[type]\n\n\t\t\tif (!timingType) {\n\t\t\t\ttimingType = timings[type] = []\n\t\t\t}\n\t\t\ttimingType.push({ desc, time: performance.now() - start })\n\t\t},\n\t}\n}\n\nexport async function time<ReturnType>(\n\tfn: Promise<ReturnType> | (() => ReturnType | Promise<ReturnType>),\n\t{\n\t\ttype,\n\t\tdesc,\n\t\ttimings,\n\t}: {\n\t\ttype: string\n\t\tdesc?: string\n\t\ttimings?: Timings\n\t},\n): Promise<ReturnType> {\n\tconst timer = createTimer(type, desc)\n\tconst promise = typeof fn === 'function' ? fn() : fn\n\tif (!timings) return promise\n\n\tconst result = await promise\n\n\ttimer.end(timings)\n\treturn result\n}\n\nexport function getServerTimeHeader(timings?: Timings) {\n\tif (!timings) return ''\n\treturn Object.entries(timings)\n\t\t.map(([key, timingInfos]) => {\n\t\t\tconst dur = timingInfos\n\t\t\t\t.reduce((acc, timingInfo) => {\n\t\t\t\t\tconst time = timingInfo.time ?? performance.now() - timingInfo.start\n\t\t\t\t\treturn acc + time\n\t\t\t\t}, 0)\n\t\t\t\t.toFixed(1)\n\t\t\tconst desc = timingInfos\n\t\t\t\t.map((t) => t.desc)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(' & ')\n\t\t\treturn [\n\t\t\t\tkey.replaceAll(/(:| |@|=|;|,|\\/|\\\\)/g, '_'),\n\t\t\t\tdesc ? `desc=${JSON.stringify(desc)}` : null,\n\t\t\t\t`dur=${dur}`,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(';')\n\t\t})\n\t\t.join(',')\n}\n\nexport function combineServerTimings(headers1: Headers, headers2: Headers) {\n\tconst newHeaders = new Headers(headers1)\n\tnewHeaders.append('Server-Timing', headers2.get('Server-Timing') ?? '')\n\treturn newHeaders.get('Server-Timing') ?? ''\n}\n\nexport function cachifiedTimingReporter<Value>(\n\ttimings?: Timings,\n): undefined | CreateReporter<Value> {\n\tif (!timings) return\n\n\treturn ({ key }) => {\n\t\tconst cacheRetrievalTimer = createTimer(\n\t\t\t`cache:${key}`,\n\t\t\t`${key} cache retrieval`,\n\t\t)\n\t\tlet getFreshValueTimer: ReturnType<typeof createTimer> | undefined\n\t\treturn (event) => {\n\t\t\tswitch (event.name) {\n\t\t\t\tcase 'getFreshValueStart':\n\t\t\t\t\tgetFreshValueTimer = createTimer(\n\t\t\t\t\t\t`getFreshValue:${key}`,\n\t\t\t\t\t\t`request forced to wait for a fresh ${key} value`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'getFreshValueSuccess':\n\t\t\t\t\tgetFreshValueTimer?.end(timings)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'done':\n\t\t\t\t\tcacheRetrievalTimer.end(timings)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.server.d.ts","sourceRoot":"","sources":["../../src/utils.server.ts"],"names":[],"mappings":"AAKA,wBAAsB,eAAe,qBAKpC;AAID,wBAAsB,UAAU,CAAC,KAAK,EACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,KAAK,GAClB,OAAO,CAAC,KAAK,CAAC,CA0BhB"}
1
+ {"version":3,"file":"utils.server.d.ts","sourceRoot":"","sources":["../../src/utils.server.ts"],"names":[],"mappings":"AAKA,wBAAsB,eAAe,qBAKpC;AAID,wBAAsB,UAAU,CAAC,KAAK,EACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,KAAK,GAClB,OAAO,CAAC,KAAK,CAAC,CAyBhB"}
@@ -19,7 +19,6 @@ export async function getPkgProp(fullPath, prop, defaultValue) {
19
19
  const propPath = prop.split('.');
20
20
  let value = pkg;
21
21
  for (const p of propPath) {
22
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
23
22
  value = value[p];
24
23
  if (value === undefined)
25
24
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.server.js","sourceRoot":"","sources":["../../src/utils.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,KAAK,UAAU,eAAe;IACpC,OAAO,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CACrC,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;AACF,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;AAE5C,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,QAAgB,EAChB,IAAY,EACZ,YAAoB;IAEpB,IAAI,GAA8B,CAAA;IAClC,IAAI,CAAC;QACJ,GAAG,GAAG,SAAS,CAAC,KAAK,CACpB,IAAI,CAAC,KAAK,CACT,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAC/D,CACD,CAAA;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,EAAE;YAC9D,KAAK,EAAE,KAAK;SACZ,CAAC,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,KAAK,GAAQ,GAAG,CAAA;IACpB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1B,sEAAsE;QACtE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAChB,IAAI,KAAK,KAAK,SAAS;YAAE,MAAK;IAC/B,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CACd,oCAAoC,IAAI,uBAAuB,QAAQ,EAAE,CACzE,CAAA;IACF,CAAC;IACD,OAAO,KAAK,IAAI,YAAY,CAAA;AAC7B,CAAC","sourcesContent":["import { promises as dns } from 'node:dns'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { z } from 'zod'\n\nexport async function checkConnection() {\n\treturn dns.resolve('example.com').then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nconst PkgSchema = z.object({}).passthrough()\n\nexport async function getPkgProp<Value>(\n\tfullPath: string,\n\tprop: string,\n\tdefaultValue?: Value,\n): Promise<Value> {\n\tlet pkg: z.infer<typeof PkgSchema>\n\ttry {\n\t\tpkg = PkgSchema.parse(\n\t\t\tJSON.parse(\n\t\t\t\tfs.readFileSync(path.join(fullPath, 'package.json')).toString(),\n\t\t\t),\n\t\t)\n\t} catch (error) {\n\t\tthrow new Error(`Could not parse package.json of ${fullPath}`, {\n\t\t\tcause: error,\n\t\t})\n\t}\n\tconst propPath = prop.split('.')\n\tlet value: any = pkg\n\tfor (const p of propPath) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\tvalue = value[p]\n\t\tif (value === undefined) break\n\t}\n\tif (value === undefined && defaultValue === undefined) {\n\t\tthrow new Error(\n\t\t\t`Could not find required property ${prop} in package.json of ${fullPath}`,\n\t\t)\n\t}\n\treturn value ?? defaultValue\n}\n"]}
1
+ {"version":3,"file":"utils.server.js","sourceRoot":"","sources":["../../src/utils.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,KAAK,UAAU,eAAe;IACpC,OAAO,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CACrC,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;AACF,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;AAE5C,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,QAAgB,EAChB,IAAY,EACZ,YAAoB;IAEpB,IAAI,GAA8B,CAAA;IAClC,IAAI,CAAC;QACJ,GAAG,GAAG,SAAS,CAAC,KAAK,CACpB,IAAI,CAAC,KAAK,CACT,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAC/D,CACD,CAAA;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,EAAE;YAC9D,KAAK,EAAE,KAAK;SACZ,CAAC,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,KAAK,GAAQ,GAAG,CAAA;IACpB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1B,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAChB,IAAI,KAAK,KAAK,SAAS;YAAE,MAAK;IAC/B,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CACd,oCAAoC,IAAI,uBAAuB,QAAQ,EAAE,CACzE,CAAA;IACF,CAAC;IACD,OAAO,KAAK,IAAI,YAAY,CAAA;AAC7B,CAAC","sourcesContent":["import { promises as dns } from 'node:dns'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { z } from 'zod'\n\nexport async function checkConnection() {\n\treturn dns.resolve('example.com').then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nconst PkgSchema = z.object({}).passthrough()\n\nexport async function getPkgProp<Value>(\n\tfullPath: string,\n\tprop: string,\n\tdefaultValue?: Value,\n): Promise<Value> {\n\tlet pkg: z.infer<typeof PkgSchema>\n\ttry {\n\t\tpkg = PkgSchema.parse(\n\t\t\tJSON.parse(\n\t\t\t\tfs.readFileSync(path.join(fullPath, 'package.json')).toString(),\n\t\t\t),\n\t\t)\n\t} catch (error) {\n\t\tthrow new Error(`Could not parse package.json of ${fullPath}`, {\n\t\t\tcause: error,\n\t\t})\n\t}\n\tconst propPath = prop.split('.')\n\tlet value: any = pkg\n\tfor (const p of propPath) {\n\t\tvalue = value[p]\n\t\tif (value === undefined) break\n\t}\n\tif (value === undefined && defaultValue === undefined) {\n\t\tthrow new Error(\n\t\t\t`Could not find required property ${prop} in package.json of ${fullPath}`,\n\t\t)\n\t}\n\treturn value ?? defaultValue\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epic-web/workshop-utils",
3
- "version": "4.5.0",
3
+ "version": "4.6.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -102,7 +102,7 @@
102
102
  "dependencies": {
103
103
  "@epic-web/cachified": "^5.2.0",
104
104
  "@epic-web/remember": "^1.0.2",
105
- "@kentcdodds/md-temp": "^8.0.1",
105
+ "@kentcdodds/md-temp": "^9.0.1",
106
106
  "@mdx-js/mdx": "^3.0.1",
107
107
  "@playwright/test": "^1.44.1",
108
108
  "@remix-run/node": "^2.9.2",