@epic-web/workshop-utils 4.0.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 (59) hide show
  1. package/README.md +3 -0
  2. package/dist/esm/apps.server.d.ts +3861 -0
  3. package/dist/esm/apps.server.d.ts.map +1 -0
  4. package/dist/esm/apps.server.js +1011 -0
  5. package/dist/esm/apps.server.js.map +1 -0
  6. package/dist/esm/cache.server.d.ts +798 -0
  7. package/dist/esm/cache.server.d.ts.map +1 -0
  8. package/dist/esm/cache.server.js +113 -0
  9. package/dist/esm/cache.server.js.map +1 -0
  10. package/dist/esm/change-tracker.server.d.ts +8 -0
  11. package/dist/esm/change-tracker.server.d.ts.map +1 -0
  12. package/dist/esm/change-tracker.server.js +32 -0
  13. package/dist/esm/change-tracker.server.js.map +1 -0
  14. package/dist/esm/codefile-mdx.server.d.ts +16 -0
  15. package/dist/esm/codefile-mdx.server.d.ts.map +1 -0
  16. package/dist/esm/codefile-mdx.server.js +275 -0
  17. package/dist/esm/codefile-mdx.server.js.map +1 -0
  18. package/dist/esm/compile-mdx.server.d.ts +11 -0
  19. package/dist/esm/compile-mdx.server.d.ts.map +1 -0
  20. package/dist/esm/compile-mdx.server.js +330 -0
  21. package/dist/esm/compile-mdx.server.js.map +1 -0
  22. package/dist/esm/db.server.d.ts +176 -0
  23. package/dist/esm/db.server.d.ts.map +1 -0
  24. package/dist/esm/db.server.js +203 -0
  25. package/dist/esm/db.server.js.map +1 -0
  26. package/dist/esm/git.server.d.ts +27 -0
  27. package/dist/esm/git.server.d.ts.map +1 -0
  28. package/dist/esm/git.server.js +93 -0
  29. package/dist/esm/git.server.js.map +1 -0
  30. package/dist/esm/iframe-sync.d.ts +10 -0
  31. package/dist/esm/iframe-sync.d.ts.map +1 -0
  32. package/dist/esm/iframe-sync.js +101 -0
  33. package/dist/esm/iframe-sync.js.map +1 -0
  34. package/dist/esm/package.json +3 -0
  35. package/dist/esm/playwright.server.d.ts +6 -0
  36. package/dist/esm/playwright.server.d.ts.map +1 -0
  37. package/dist/esm/playwright.server.js +94 -0
  38. package/dist/esm/playwright.server.js.map +1 -0
  39. package/dist/esm/process-manager.server.d.ts +78 -0
  40. package/dist/esm/process-manager.server.d.ts.map +1 -0
  41. package/dist/esm/process-manager.server.js +267 -0
  42. package/dist/esm/process-manager.server.js.map +1 -0
  43. package/dist/esm/test.d.ts +9 -0
  44. package/dist/esm/test.d.ts.map +1 -0
  45. package/dist/esm/test.js +45 -0
  46. package/dist/esm/test.js.map +1 -0
  47. package/dist/esm/timing.server.d.ts +20 -0
  48. package/dist/esm/timing.server.d.ts.map +1 -0
  49. package/dist/esm/timing.server.js +89 -0
  50. package/dist/esm/timing.server.js.map +1 -0
  51. package/dist/esm/utils.d.ts +2 -0
  52. package/dist/esm/utils.d.ts.map +1 -0
  53. package/dist/esm/utils.js +13 -0
  54. package/dist/esm/utils.js.map +1 -0
  55. package/dist/esm/utils.server.d.ts +3 -0
  56. package/dist/esm/utils.server.d.ts.map +1 -0
  57. package/dist/esm/utils.server.js +32 -0
  58. package/dist/esm/utils.server.js.map +1 -0
  59. package/package.json +171 -0
@@ -0,0 +1,330 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { cachified } from '@epic-web/cachified';
4
+ import { remember } from '@epic-web/remember';
5
+ import { remarkCodeBlocksShiki } from '@kentcdodds/md-temp';
6
+ import fsExtra from 'fs-extra';
7
+ import md5 from 'md5-hex';
8
+ import { bundleMDX } from 'mdx-bundler';
9
+ import PQueue from 'p-queue';
10
+ import remarkAutolinkHeadings from 'remark-autolink-headings';
11
+ import emoji from 'remark-emoji';
12
+ import gfm from 'remark-gfm';
13
+ import { visit } from 'unist-util-visit';
14
+ import { compiledMarkdownCache, embeddedFilesCache, shouldForceFresh, } from './cache.server.js';
15
+ import { remarkCodeFile, } from './codefile-mdx.server.js';
16
+ const cacheDir = path.join(process.env.EPICSHOP_CONTEXT_CWD ?? process.cwd(), './node_modules/.cache/compile-mdx');
17
+ function trimCodeBlocks() {
18
+ return async function transformer(tree) {
19
+ visit(tree, 'element', (preNode) => {
20
+ if (preNode.tagName !== 'pre' || !preNode.children.length) {
21
+ return;
22
+ }
23
+ const codeNode = preNode.children[0];
24
+ if (!codeNode ||
25
+ codeNode.type !== 'element' ||
26
+ codeNode.tagName !== 'code') {
27
+ return;
28
+ }
29
+ const [codeStringNode] = codeNode.children;
30
+ if (!codeStringNode)
31
+ return;
32
+ if (codeStringNode.type !== 'text') {
33
+ console.warn(`trimCodeBlocks: Unexpected: codeStringNode type is not "text": ${codeStringNode.type}`);
34
+ return;
35
+ }
36
+ codeStringNode.value = codeStringNode.value.trimEnd();
37
+ });
38
+ };
39
+ }
40
+ function removePreContainerDivs() {
41
+ return async function preContainerDivsTransformer(tree) {
42
+ visit(tree, { type: 'element', tagName: 'pre' }, function visitor(node, index, parent) {
43
+ if (parent?.type !== 'element')
44
+ return;
45
+ if (parent.tagName !== 'div')
46
+ return;
47
+ if (parent.children.length !== 1 && index === 0)
48
+ return;
49
+ Object.assign(parent, node);
50
+ });
51
+ };
52
+ }
53
+ const rehypePlugins = [
54
+ trimCodeBlocks,
55
+ remarkCodeBlocksShiki,
56
+ removePreContainerDivs,
57
+ ];
58
+ function checkFileExists(file) {
59
+ return fs.promises.access(file, fs.constants.F_OK).then(() => true, () => false);
60
+ }
61
+ const verboseLog = process.env.EPICSHOP_VERBOSE_LOG === 'true' ? console.log : () => { };
62
+ /**
63
+ * @param embeddedFiles {string[]} - list of embedded files
64
+ * @param lastCompiledTime {number} - timestamp indicating the last time mdx file was compiled
65
+ * @returns true if all embedded file mtimeMs are older then the file compiled time,
66
+ * false if we need update
67
+ */
68
+ function validateEmbeddedFiles(embeddedFiles, lastCompiledTime) {
69
+ if (process.env.NODE_ENV !== 'development')
70
+ return Promise.resolve(true);
71
+ return Promise.all(Array.from(embeddedFiles).map(async ({ file }) => {
72
+ const stat = await fs.promises.stat(file).catch(() => ({ mtimeMs: 0 }));
73
+ return lastCompiledTime > stat.mtimeMs || Promise.reject();
74
+ })).then(() => true, () => false);
75
+ }
76
+ export async function compileMdx(file, { request, forceFresh } = {}) {
77
+ if (!(await checkFileExists(file))) {
78
+ throw new Error(`File does not exist: ${file}`);
79
+ }
80
+ let cachedEmbeddedFiles = new Map();
81
+ const stat = await fs.promises.stat(file);
82
+ const cacheLocation = path.join(cacheDir, `${md5(file)}.json`);
83
+ const requireFresh = await shouldForceFresh({
84
+ forceFresh,
85
+ request,
86
+ key: cacheLocation,
87
+ });
88
+ if (!requireFresh && (await checkFileExists(cacheLocation))) {
89
+ const cached = JSON.parse(await fs.promises.readFile(cacheLocation, 'utf-8'));
90
+ cachedEmbeddedFiles = new Map(Object.entries(cached.value.embeddedFiles ?? {}));
91
+ const compiledTime = cached.value.compiledTime ?? 0;
92
+ const warningCancled = process.env.NODE_ENV === 'development'
93
+ ? cached?.value?.warningCancled ?? false
94
+ : false;
95
+ if (compiledTime > stat.mtimeMs &&
96
+ !warningCancled &&
97
+ (await validateEmbeddedFiles(cachedEmbeddedFiles.values(), compiledTime))) {
98
+ return cached.value;
99
+ }
100
+ }
101
+ let title = null;
102
+ const epicVideoEmbeds = [];
103
+ const codeFileData = {
104
+ mdxFile: file,
105
+ cacheLocation,
106
+ cachedEmbeddedFiles,
107
+ embeddedFiles: new Map(),
108
+ };
109
+ try {
110
+ verboseLog(`Compiling ${file}`);
111
+ const bundleResult = await queuedBundleMDX({
112
+ file,
113
+ cwd: path.dirname(file),
114
+ esbuildOptions(options) {
115
+ options.define = {
116
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'production'),
117
+ ...options.define,
118
+ };
119
+ return options;
120
+ },
121
+ mdxOptions(options) {
122
+ options.remarkPlugins = [
123
+ ...(options.remarkPlugins ?? []),
124
+ [remarkAutolinkHeadings, { behavior: 'wrap' }],
125
+ gfm,
126
+ () => (tree) => {
127
+ visit(tree, 'heading', node => {
128
+ if (title)
129
+ return;
130
+ if (node.depth === 1) {
131
+ visit(node, 'text', textNode => {
132
+ title = textNode.value.trim();
133
+ });
134
+ }
135
+ });
136
+ title = title ? title.replace(/^\d+\. /, '').trim() : null;
137
+ },
138
+ () => (tree) => {
139
+ visit(tree, 'mdxJsxFlowElement', jsxEl => {
140
+ if (jsxEl.name !== 'EpicVideo')
141
+ return;
142
+ const urlAttr = jsxEl.attributes.find(a => a.type === 'mdxJsxAttribute' && a.name === 'url');
143
+ if (!urlAttr)
144
+ return;
145
+ let url = urlAttr.value;
146
+ if (typeof url !== 'string')
147
+ return;
148
+ if (url.endsWith('/'))
149
+ url = url.slice(0, -1);
150
+ epicVideoEmbeds.push(url);
151
+ });
152
+ },
153
+ () => remarkCodeFile(codeFileData),
154
+ emoji,
155
+ ];
156
+ options.rehypePlugins = [
157
+ ...(options.rehypePlugins ?? []),
158
+ ...rehypePlugins,
159
+ ];
160
+ options.mdxExtensions = ['.mdx', '.md'];
161
+ options.format = 'mdx';
162
+ options.development = false;
163
+ return options;
164
+ },
165
+ });
166
+ if (!bundleResult)
167
+ throw new Error(`Timeout for file: ${file}`);
168
+ const result = { code: bundleResult.code, title, epicVideoEmbeds };
169
+ await fsExtra.ensureDir(cacheDir);
170
+ await fs.promises.writeFile(cacheLocation, JSON.stringify({
171
+ value: {
172
+ ...result,
173
+ compiledTime: Date.now(),
174
+ embeddedFiles: codeFileData.embeddedFiles.size
175
+ ? Object.fromEntries(codeFileData.embeddedFiles)
176
+ : undefined,
177
+ },
178
+ }));
179
+ await updateEmbeddedFilesCache(codeFileData);
180
+ return result;
181
+ }
182
+ catch (error) {
183
+ console.error(`Compilation error for file: `, file, error);
184
+ throw error;
185
+ }
186
+ finally {
187
+ verboseLog(`Successfully compiled ${file}`);
188
+ }
189
+ }
190
+ export async function compileMarkdownString(markdownString) {
191
+ return cachified({
192
+ key: markdownString,
193
+ cache: compiledMarkdownCache,
194
+ ttl: 1000 * 60 * 60 * 24,
195
+ getFreshValue: async () => {
196
+ try {
197
+ verboseLog(`Compiling string`, markdownString);
198
+ const result = await queuedBundleMDX({
199
+ source: markdownString,
200
+ esbuildOptions(options) {
201
+ options.define = {
202
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'production'),
203
+ ...options.define,
204
+ };
205
+ return options;
206
+ },
207
+ mdxOptions(options) {
208
+ options.rehypePlugins = [
209
+ ...(options.rehypePlugins ?? []),
210
+ ...rehypePlugins,
211
+ ];
212
+ options.development = false;
213
+ return options;
214
+ },
215
+ });
216
+ if (!result)
217
+ throw new Error(`Timed out compiling markdown string`);
218
+ return result.code;
219
+ }
220
+ catch (error) {
221
+ console.error(`Compilation error for code: `, markdownString, error);
222
+ throw error;
223
+ }
224
+ finally {
225
+ verboseLog(`Successfully compiled string`, markdownString);
226
+ }
227
+ },
228
+ });
229
+ }
230
+ const modifiedEmbeddedFilesTime = remember('modified_embedded_files_time', () => new Map());
231
+ const EMBEDDED_FILES_CACHE_KEY = 'embeddedFilesCache';
232
+ async function updateEmbeddedFilesCache({ mdxFile, embeddedFiles, }) {
233
+ if (mdxFile.includes('playground'))
234
+ return;
235
+ let cachedList = await getEmbeddedFilesCache();
236
+ const hash = cachedList ? md5(JSON.stringify(cachedList)) : null;
237
+ // make sure we get clean list before updating it
238
+ if (cachedList) {
239
+ for (const [key, value] of Object.entries(cachedList)) {
240
+ cachedList[key] = value.filter(item => item !== mdxFile);
241
+ if (cachedList[key]?.length === 0) {
242
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
243
+ delete cachedList[key];
244
+ }
245
+ }
246
+ }
247
+ if (embeddedFiles.size) {
248
+ if (!cachedList) {
249
+ cachedList = {};
250
+ }
251
+ const files = Array.from(new Set(Array.from(embeddedFiles.values()).map(({ file }) => file))).sort();
252
+ for (const file of files) {
253
+ cachedList[file] = [...(cachedList[file] ?? []), mdxFile];
254
+ }
255
+ }
256
+ if (cachedList && hash !== md5(JSON.stringify(cachedList))) {
257
+ await fsExtra.ensureDir(cacheDir);
258
+ const embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json');
259
+ modifiedEmbeddedFilesTime.set(EMBEDDED_FILES_CACHE_KEY, Date.now());
260
+ await fs.promises.writeFile(embeddedFilesLocation, JSON.stringify({ ...cachedList }));
261
+ }
262
+ }
263
+ async function getEmbeddedFilesCache() {
264
+ const key = EMBEDDED_FILES_CACHE_KEY;
265
+ function getForceFresh(cacheEntry) {
266
+ if (!cacheEntry)
267
+ return true;
268
+ const latestModifiedTime = modifiedEmbeddedFilesTime.get(key);
269
+ if (!latestModifiedTime)
270
+ return undefined;
271
+ return latestModifiedTime > cacheEntry.metadata.createdTime
272
+ ? true
273
+ : undefined;
274
+ }
275
+ return cachified({
276
+ key,
277
+ cache: embeddedFilesCache,
278
+ ttl: 1000 * 60 * 60 * 24,
279
+ forceFresh: getForceFresh(embeddedFilesCache.get(key)),
280
+ getFreshValue: async () => {
281
+ try {
282
+ const embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json');
283
+ if (await checkFileExists(embeddedFilesLocation)) {
284
+ return JSON.parse(await fs.promises.readFile(embeddedFilesLocation, 'utf-8'));
285
+ }
286
+ }
287
+ catch (error) {
288
+ console.error(`Unable to read 'embeddedFiles.json' from: `, cacheDir);
289
+ }
290
+ return undefined;
291
+ },
292
+ });
293
+ }
294
+ export async function isEmbeddedFile(filePath) {
295
+ if (process.env.NODE_ENV !== 'development')
296
+ return false;
297
+ const embeddedFilesList = await getEmbeddedFilesCache();
298
+ if (embeddedFilesList) {
299
+ const embeddedFiles = Object.keys(embeddedFilesList);
300
+ return embeddedFiles.includes(filePath.replace(/\\/g, '/'));
301
+ }
302
+ return false;
303
+ }
304
+ let _queue = null;
305
+ async function getQueue() {
306
+ if (_queue)
307
+ return _queue;
308
+ _queue = new PQueue({
309
+ concurrency: 1,
310
+ throwOnTimeout: true,
311
+ timeout: 1000 * 60,
312
+ });
313
+ return _queue;
314
+ }
315
+ // We have to use a queue because we can't run more than one of these at a time
316
+ // or we'll hit an out of memory error because esbuild uses a lot of memory...
317
+ async function queuedBundleMDX(...args) {
318
+ const queue = await getQueue();
319
+ const result = await queue.add(() => bundleMDX(...args));
320
+ return result;
321
+ }
322
+ // TODO: Fix these
323
+ /*
324
+ eslint
325
+ "@typescript-eslint/no-unsafe-assignment": "off",
326
+ "@typescript-eslint/no-unsafe-member-access": "off",
327
+ "@typescript-eslint/no-unnecessary-condition": "off",
328
+ "@typescript-eslint/no-unsafe-argument": "off",
329
+ */
330
+ //# sourceMappingURL=compile-mdx.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-mdx.server.js","sourceRoot":"","sources":["../../src/compile-mdx.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,SAAS,EAAmB,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,OAAO,MAAM,UAAU,CAAA;AAE9B,OAAO,GAAG,MAAM,SAAS,CAAA;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,MAAM,MAAM,SAAS,CAAA;AAC5B,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,MAAM,cAAc,CAAA;AAChC,OAAO,GAAG,MAAM,YAAY,CAAA;AAE5B,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAEN,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACN,cAAc,GAGd,MAAM,0BAA0B,CAAA;AAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACzB,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,EAAE,EACjD,mCAAmC,CACnC,CAAA;AAED,SAAS,cAAc;IACtB,OAAO,KAAK,UAAU,WAAW,CAAC,IAAc;QAC/C,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE;YAC3C,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC3D,OAAM;YACP,CAAC;YACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YACpC,IACC,CAAC,QAAQ;gBACT,QAAQ,CAAC,IAAI,KAAK,SAAS;gBAC3B,QAAQ,CAAC,OAAO,KAAK,MAAM,EAC1B,CAAC;gBACF,OAAM;YACP,CAAC;YACD,MAAM,CAAC,cAAc,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAA;YAC1C,IAAI,CAAC,cAAc;gBAAE,OAAM;YAE3B,IAAI,cAAc,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpC,OAAO,CAAC,IAAI,CACX,kEAAkE,cAAc,CAAC,IAAI,EAAE,CACvF,CAAA;gBACD,OAAM;YACP,CAAC;YACD,cAAc,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,CAAA;QACtD,CAAC,CAAC,CAAA;IACH,CAAC,CAAA;AACF,CAAC;AAED,SAAS,sBAAsB;IAC9B,OAAO,KAAK,UAAU,2BAA2B,CAAC,IAAc;QAC/D,KAAK,CACJ,IAAI,EACJ,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,EACnC,SAAS,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM;YACnC,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS;gBAAE,OAAM;YACtC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK;gBAAE,OAAM;YACpC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAM;YACvD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAC5B,CAAC,CACD,CAAA;IACF,CAAC,CAAA;AACF,CAAC;AAED,MAAM,aAAa,GAAG;IACrB,cAAc;IACd,qBAAqB;IACrB,sBAAsB;CACE,CAAA;AAEzB,SAAS,eAAe,CAAC,IAAY;IACpC,OAAO,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CACtD,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;AACF,CAAC;AAED,MAAM,UAAU,GACf,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAErE;;;;;GAKG;AACH,SAAS,qBAAqB,CAC7B,aAA6C,EAC7C,gBAAwB;IAExB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACxE,OAAO,OAAO,CAAC,GAAG,CACjB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QAChD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACvE,OAAO,gBAAgB,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAA;IAC3D,CAAC,CAAC,CACF,CAAC,IAAI,CACL,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,IAAY,EACZ,EAAE,OAAO,EAAE,UAAU,KAAkD,EAAE;IAMzE,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,mBAAmB,GAAG,IAAI,GAAG,EAAwB,CAAA;IAEzD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAE9D,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC;QAC3C,UAAU;QACV,OAAO;QACP,GAAG,EAAE,aAAa;KAClB,CAAC,CAAA;IACF,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAC3C,CAAA;QAER,mBAAmB,GAAG,IAAI,GAAG,CAC5B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAChD,CAAA;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;QACnD,MAAM,cAAc,GACnB,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;YACrC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,IAAI,KAAK;YACxC,CAAC,CAAC,KAAK,CAAA;QACT,IACC,YAAY,GAAG,IAAI,CAAC,OAAO;YAC3B,CAAC,cAAc;YACf,CAAC,MAAM,qBAAqB,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,EACxE,CAAC;YACF,OAAO,MAAM,CAAC,KAAK,CAAA;QACpB,CAAC;IACF,CAAC;IACD,IAAI,KAAK,GAAkB,IAAI,CAAA;IAC/B,MAAM,eAAe,GAAkB,EAAE,CAAA;IACzC,MAAM,YAAY,GAAG;QACpB,OAAO,EAAE,IAAI;QACb,aAAa;QACb,mBAAmB;QACnB,aAAa,EAAE,IAAI,GAAG,EAAwB;KAC9C,CAAA;IAED,IAAI,CAAC;QACJ,UAAU,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;QAC/B,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;YAC1C,IAAI;YACJ,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACvB,cAAc,CAAC,OAAO;gBACrB,OAAO,CAAC,MAAM,GAAG;oBAChB,sBAAsB,EAAE,IAAI,CAAC,SAAS,CACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,CACpC;oBACD,GAAG,OAAO,CAAC,MAAM;iBACjB,CAAA;gBACD,OAAO,OAAO,CAAA;YACf,CAAC;YACD,UAAU,CAAC,OAAO;gBACjB,OAAO,CAAC,aAAa,GAAG;oBACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;oBAChC,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC9C,GAAG;oBACH,GAAG,EAAE,CAAC,CAAC,IAAe,EAAE,EAAE;wBACzB,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;4BAC7B,IAAI,KAAK;gCAAE,OAAM;4BACjB,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gCACtB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE;oCAC9B,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;gCAC9B,CAAC,CAAC,CAAA;4BACH,CAAC;wBACF,CAAC,CAAC,CAAA;wBACF,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;oBAC3D,CAAC;oBACD,GAAG,EAAE,CAAC,CAAC,IAAe,EAAE,EAAE;wBACzB,KAAK,CAAC,IAAI,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE;4BACxC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gCAAE,OAAM;4BACtC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CACrD,CAAA;4BACD,IAAI,CAAC,OAAO;gCAAE,OAAM;4BACpB,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAA;4BACvB,IAAI,OAAO,GAAG,KAAK,QAAQ;gCAAE,OAAM;4BACnC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;gCAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;4BAC7C,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;wBAC1B,CAAC,CAAC,CAAA;oBACH,CAAC;oBACD,GAAG,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC;oBAClC,KAAK;iBACL,CAAA;gBACD,OAAO,CAAC,aAAa,GAAG;oBACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;oBAChC,GAAG,aAAa;iBAChB,CAAA;gBACD,OAAO,CAAC,aAAa,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;gBACvC,OAAO,CAAC,MAAM,GAAG,KAAK,CAAA;gBACtB,OAAO,CAAC,WAAW,GAAG,KAAK,CAAA;gBAC3B,OAAO,OAAO,CAAA;YACf,CAAC;SACD,CAAC,CAAA;QACF,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAA;QAE/D,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,eAAe,EAAE,CAAA;QAClE,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACjC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAC1B,aAAa,EACb,IAAI,CAAC,SAAS,CAAC;YACd,KAAK,EAAE;gBACN,GAAG,MAAM;gBACT,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;gBACxB,aAAa,EAAE,YAAY,CAAC,aAAa,CAAC,IAAI;oBAC7C,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,aAAa,CAAC;oBAChD,CAAC,CAAC,SAAS;aACZ;SACD,CAAC,CACF,CAAA;QACD,MAAM,wBAAwB,CAAC,YAAY,CAAC,CAAA;QAC5C,OAAO,MAAM,CAAA;IACd,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAC1D,MAAM,KAAK,CAAA;IACZ,CAAC;YAAS,CAAC;QACV,UAAU,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAA;IAC5C,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,cAAsB;IACjE,OAAO,SAAS,CAAC;QAChB,GAAG,EAAE,cAAc;QACnB,KAAK,EAAE,qBAAqB;QAC5B,GAAG,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACxB,aAAa,EAAE,KAAK,IAAI,EAAE;YACzB,IAAI,CAAC;gBACJ,UAAU,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAA;gBAC9C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;oBACpC,MAAM,EAAE,cAAc;oBACtB,cAAc,CAAC,OAAO;wBACrB,OAAO,CAAC,MAAM,GAAG;4BAChB,sBAAsB,EAAE,IAAI,CAAC,SAAS,CACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,CACpC;4BACD,GAAG,OAAO,CAAC,MAAM;yBACjB,CAAA;wBACD,OAAO,OAAO,CAAA;oBACf,CAAC;oBACD,UAAU,CAAC,OAAO;wBACjB,OAAO,CAAC,aAAa,GAAG;4BACvB,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;4BAChC,GAAG,aAAa;yBAChB,CAAA;wBACD,OAAO,CAAC,WAAW,GAAG,KAAK,CAAA;wBAC3B,OAAO,OAAO,CAAA;oBACf,CAAC;iBACD,CAAC,CAAA;gBACF,IAAI,CAAC,MAAM;oBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;gBAEnE,OAAO,MAAM,CAAC,IAAI,CAAA;YACnB,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,cAAc,EAAE,KAAK,CAAC,CAAA;gBACpE,MAAM,KAAK,CAAA;YACZ,CAAC;oBAAS,CAAC;gBACV,UAAU,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAA;YAC3D,CAAC;QACF,CAAC;KACD,CAAC,CAAA;AACH,CAAC;AAED,MAAM,yBAAyB,GAAG,QAAQ,CACzC,8BAA8B,EAC9B,GAAG,EAAE,CAAC,IAAI,GAAG,EAAkB,CAC/B,CAAA;AAED,MAAM,wBAAwB,GAAG,oBAAoB,CAAA;AAErD,KAAK,UAAU,wBAAwB,CAAC,EACvC,OAAO,EACP,aAAa,GACC;IACd,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAM;IAC1C,IAAI,UAAU,GAAG,MAAM,qBAAqB,EAAE,CAAA;IAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAEhE,iDAAiD;IACjD,IAAI,UAAU,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACvD,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAA;YACxD,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,gEAAgE;gBAChE,OAAO,UAAU,CAAC,GAAG,CAAC,CAAA;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,UAAU,GAAG,EAAE,CAAA;QAChB,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CACnE,CAAC,IAAI,EAAE,CAAA;QACR,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;QAC1D,CAAC;IACF,CAAC;IAED,IAAI,UAAU,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACjC,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAA;QACvE,yBAAyB,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QACnE,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAC1B,qBAAqB,EACrB,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CACjC,CAAA;IACF,CAAC;AACF,CAAC;AAED,KAAK,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,wBAAwB,CAAA;IAEpC,SAAS,aAAa,CAAC,UAAyC;QAC/D,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAA;QAC5B,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC7D,IAAI,CAAC,kBAAkB;YAAE,OAAO,SAAS,CAAA;QACzC,OAAO,kBAAkB,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW;YAC1D,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,SAAS,CAAA;IACb,CAAC;IAED,OAAO,SAAS,CAAC;QAChB,GAAG;QACH,KAAK,EAAE,kBAAkB;QACzB,GAAG,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACxB,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtD,aAAa,EAAE,KAAK,IAAI,EAAE;YACzB,IAAI,CAAC;gBACJ,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAA;gBACvE,IAAI,MAAM,eAAe,CAAC,qBAAqB,CAAC,EAAE,CAAC;oBAClD,OAAO,IAAI,CAAC,KAAK,CAChB,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAC/B,CAAA;gBAC7B,CAAC;YACF,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,QAAQ,CAAC,CAAA;YACtE,CAAC;YACD,OAAO,SAAS,CAAA;QACjB,CAAC;KACD,CAAC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,KAAK,CAAA;IACxD,MAAM,iBAAiB,GAAG,MAAM,qBAAqB,EAAE,CAAA;IACvD,IAAI,iBAAiB,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACpD,OAAO,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,KAAK,CAAA;AACb,CAAC;AAED,IAAI,MAAM,GAAkB,IAAI,CAAA;AAChC,KAAK,UAAU,QAAQ;IACtB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,MAAM,GAAG,IAAI,MAAM,CAAC;QACnB,WAAW,EAAE,CAAC;QACd,cAAc,EAAE,IAAI;QACpB,OAAO,EAAE,IAAI,GAAG,EAAE;KAClB,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACd,CAAC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,KAAK,UAAU,eAAe,CAAC,GAAG,IAAkC;IACnE,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAA;IAC9B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;IACxD,OAAO,MAAM,CAAA;AACd,CAAC;AAED,kBAAkB;AAClB;;;;;;EAME","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { cachified, type CacheEntry } from '@epic-web/cachified'\nimport { remember } from '@epic-web/remember'\nimport { remarkCodeBlocksShiki } from '@kentcdodds/md-temp'\nimport fsExtra from 'fs-extra'\nimport { type Element, type Root as HastRoot } from 'hast'\nimport md5 from 'md5-hex'\nimport { type Root as MdastRoot } from 'mdast'\nimport { bundleMDX } from 'mdx-bundler'\nimport PQueue from 'p-queue'\nimport remarkAutolinkHeadings from 'remark-autolink-headings'\nimport emoji from 'remark-emoji'\nimport gfm from 'remark-gfm'\nimport { type PluggableList } from 'unified'\nimport { visit } from 'unist-util-visit'\nimport {\n\ttype CachedEmbeddedFilesList,\n\tcompiledMarkdownCache,\n\tembeddedFilesCache,\n\tshouldForceFresh,\n} from './cache.server.js'\nimport {\n\tremarkCodeFile,\n\ttype CodeFileData,\n\ttype EmbeddedFile,\n} from './codefile-mdx.server.js'\n\nconst cacheDir = path.join(\n\tprocess.env.EPICSHOP_CONTEXT_CWD ?? process.cwd(),\n\t'./node_modules/.cache/compile-mdx',\n)\n\nfunction trimCodeBlocks() {\n\treturn async function transformer(tree: HastRoot) {\n\t\tvisit(tree, 'element', (preNode: Element) => {\n\t\t\tif (preNode.tagName !== 'pre' || !preNode.children.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst codeNode = preNode.children[0]\n\t\t\tif (\n\t\t\t\t!codeNode ||\n\t\t\t\tcodeNode.type !== 'element' ||\n\t\t\t\tcodeNode.tagName !== 'code'\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [codeStringNode] = codeNode.children\n\t\t\tif (!codeStringNode) return\n\n\t\t\tif (codeStringNode.type !== 'text') {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`trimCodeBlocks: Unexpected: codeStringNode type is not \"text\": ${codeStringNode.type}`,\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcodeStringNode.value = codeStringNode.value.trimEnd()\n\t\t})\n\t}\n}\n\nfunction removePreContainerDivs() {\n\treturn async function preContainerDivsTransformer(tree: HastRoot) {\n\t\tvisit(\n\t\t\ttree,\n\t\t\t{ type: 'element', tagName: 'pre' },\n\t\t\tfunction visitor(node, index, parent) {\n\t\t\t\tif (parent?.type !== 'element') return\n\t\t\t\tif (parent.tagName !== 'div') return\n\t\t\t\tif (parent.children.length !== 1 && index === 0) return\n\t\t\t\tObject.assign(parent, node)\n\t\t\t},\n\t\t)\n\t}\n}\n\nconst rehypePlugins = [\n\ttrimCodeBlocks,\n\tremarkCodeBlocksShiki,\n\tremovePreContainerDivs,\n] satisfies PluggableList\n\nfunction checkFileExists(file: string) {\n\treturn fs.promises.access(file, fs.constants.F_OK).then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nconst verboseLog =\n\tprocess.env.EPICSHOP_VERBOSE_LOG === 'true' ? console.log : () => {}\n\n/**\n * @param embeddedFiles {string[]} - list of embedded files\n * @param lastCompiledTime {number} - timestamp indicating the last time mdx file was compiled\n * @returns true if all embedded file mtimeMs are older then the file compiled time,\n * false if we need update\n */\nfunction validateEmbeddedFiles(\n\tembeddedFiles: IterableIterator<EmbeddedFile>,\n\tlastCompiledTime: number,\n): Promise<boolean> {\n\tif (process.env.NODE_ENV !== 'development') return Promise.resolve(true)\n\treturn Promise.all(\n\t\tArray.from(embeddedFiles).map(async ({ file }) => {\n\t\t\tconst stat = await fs.promises.stat(file).catch(() => ({ mtimeMs: 0 }))\n\t\t\treturn lastCompiledTime > stat.mtimeMs || Promise.reject()\n\t\t}),\n\t).then(\n\t\t() => true,\n\t\t() => false,\n\t)\n}\n\nexport async function compileMdx(\n\tfile: string,\n\t{ request, forceFresh }: { request?: Request; forceFresh?: boolean } = {},\n): Promise<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}> {\n\tif (!(await checkFileExists(file))) {\n\t\tthrow new Error(`File does not exist: ${file}`)\n\t}\n\n\tlet cachedEmbeddedFiles = new Map<string, EmbeddedFile>()\n\n\tconst stat = await fs.promises.stat(file)\n\tconst cacheLocation = path.join(cacheDir, `${md5(file)}.json`)\n\n\tconst requireFresh = await shouldForceFresh({\n\t\tforceFresh,\n\t\trequest,\n\t\tkey: cacheLocation,\n\t})\n\tif (!requireFresh && (await checkFileExists(cacheLocation))) {\n\t\tconst cached = JSON.parse(\n\t\t\tawait fs.promises.readFile(cacheLocation, 'utf-8'),\n\t\t) as any\n\n\t\tcachedEmbeddedFiles = new Map(\n\t\t\tObject.entries(cached.value.embeddedFiles ?? {}),\n\t\t)\n\n\t\tconst compiledTime = cached.value.compiledTime ?? 0\n\t\tconst warningCancled =\n\t\t\tprocess.env.NODE_ENV === 'development'\n\t\t\t\t? cached?.value?.warningCancled ?? false\n\t\t\t\t: false\n\t\tif (\n\t\t\tcompiledTime > stat.mtimeMs &&\n\t\t\t!warningCancled &&\n\t\t\t(await validateEmbeddedFiles(cachedEmbeddedFiles.values(), compiledTime))\n\t\t) {\n\t\t\treturn cached.value\n\t\t}\n\t}\n\tlet title: string | null = null\n\tconst epicVideoEmbeds: Array<string> = []\n\tconst codeFileData = {\n\t\tmdxFile: file,\n\t\tcacheLocation,\n\t\tcachedEmbeddedFiles,\n\t\tembeddedFiles: new Map<string, EmbeddedFile>(),\n\t}\n\n\ttry {\n\t\tverboseLog(`Compiling ${file}`)\n\t\tconst bundleResult = await queuedBundleMDX({\n\t\t\tfile,\n\t\t\tcwd: path.dirname(file),\n\t\t\tesbuildOptions(options) {\n\t\t\t\toptions.define = {\n\t\t\t\t\t'process.env.NODE_ENV': JSON.stringify(\n\t\t\t\t\t\tprocess.env.NODE_ENV ?? 'production',\n\t\t\t\t\t),\n\t\t\t\t\t...options.define,\n\t\t\t\t}\n\t\t\t\treturn options\n\t\t\t},\n\t\t\tmdxOptions(options) {\n\t\t\t\toptions.remarkPlugins = [\n\t\t\t\t\t...(options.remarkPlugins ?? []),\n\t\t\t\t\t[remarkAutolinkHeadings, { behavior: 'wrap' }],\n\t\t\t\t\tgfm,\n\t\t\t\t\t() => (tree: MdastRoot) => {\n\t\t\t\t\t\tvisit(tree, 'heading', node => {\n\t\t\t\t\t\t\tif (title) return\n\t\t\t\t\t\t\tif (node.depth === 1) {\n\t\t\t\t\t\t\t\tvisit(node, 'text', textNode => {\n\t\t\t\t\t\t\t\t\ttitle = textNode.value.trim()\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\ttitle = title ? title.replace(/^\\d+\\. /, '').trim() : null\n\t\t\t\t\t},\n\t\t\t\t\t() => (tree: MdastRoot) => {\n\t\t\t\t\t\tvisit(tree, 'mdxJsxFlowElement', jsxEl => {\n\t\t\t\t\t\t\tif (jsxEl.name !== 'EpicVideo') return\n\t\t\t\t\t\t\tconst urlAttr = jsxEl.attributes.find(\n\t\t\t\t\t\t\t\ta => a.type === 'mdxJsxAttribute' && a.name === 'url',\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (!urlAttr) return\n\t\t\t\t\t\t\tlet url = urlAttr.value\n\t\t\t\t\t\t\tif (typeof url !== 'string') return\n\t\t\t\t\t\t\tif (url.endsWith('/')) url = url.slice(0, -1)\n\t\t\t\t\t\t\tepicVideoEmbeds.push(url)\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t\t() => remarkCodeFile(codeFileData),\n\t\t\t\t\temoji,\n\t\t\t\t]\n\t\t\t\toptions.rehypePlugins = [\n\t\t\t\t\t...(options.rehypePlugins ?? []),\n\t\t\t\t\t...rehypePlugins,\n\t\t\t\t]\n\t\t\t\toptions.mdxExtensions = ['.mdx', '.md']\n\t\t\t\toptions.format = 'mdx'\n\t\t\t\toptions.development = false\n\t\t\t\treturn options\n\t\t\t},\n\t\t})\n\t\tif (!bundleResult) throw new Error(`Timeout for file: ${file}`)\n\n\t\tconst result = { code: bundleResult.code, title, epicVideoEmbeds }\n\t\tawait fsExtra.ensureDir(cacheDir)\n\t\tawait fs.promises.writeFile(\n\t\t\tcacheLocation,\n\t\t\tJSON.stringify({\n\t\t\t\tvalue: {\n\t\t\t\t\t...result,\n\t\t\t\t\tcompiledTime: Date.now(),\n\t\t\t\t\tembeddedFiles: codeFileData.embeddedFiles.size\n\t\t\t\t\t\t? Object.fromEntries(codeFileData.embeddedFiles)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t}),\n\t\t)\n\t\tawait updateEmbeddedFilesCache(codeFileData)\n\t\treturn result\n\t} catch (error: unknown) {\n\t\tconsole.error(`Compilation error for file: `, file, error)\n\t\tthrow error\n\t} finally {\n\t\tverboseLog(`Successfully compiled ${file}`)\n\t}\n}\n\nexport async function compileMarkdownString(markdownString: string) {\n\treturn cachified({\n\t\tkey: markdownString,\n\t\tcache: compiledMarkdownCache,\n\t\tttl: 1000 * 60 * 60 * 24,\n\t\tgetFreshValue: async () => {\n\t\t\ttry {\n\t\t\t\tverboseLog(`Compiling string`, markdownString)\n\t\t\t\tconst result = await queuedBundleMDX({\n\t\t\t\t\tsource: markdownString,\n\t\t\t\t\tesbuildOptions(options) {\n\t\t\t\t\t\toptions.define = {\n\t\t\t\t\t\t\t'process.env.NODE_ENV': JSON.stringify(\n\t\t\t\t\t\t\t\tprocess.env.NODE_ENV ?? 'production',\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t...options.define,\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn options\n\t\t\t\t\t},\n\t\t\t\t\tmdxOptions(options) {\n\t\t\t\t\t\toptions.rehypePlugins = [\n\t\t\t\t\t\t\t...(options.rehypePlugins ?? []),\n\t\t\t\t\t\t\t...rehypePlugins,\n\t\t\t\t\t\t]\n\t\t\t\t\t\toptions.development = false\n\t\t\t\t\t\treturn options\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tif (!result) throw new Error(`Timed out compiling markdown string`)\n\n\t\t\t\treturn result.code\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconsole.error(`Compilation error for code: `, markdownString, error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tverboseLog(`Successfully compiled string`, markdownString)\n\t\t\t}\n\t\t},\n\t})\n}\n\nconst modifiedEmbeddedFilesTime = remember(\n\t'modified_embedded_files_time',\n\t() => new Map<string, number>(),\n)\n\nconst EMBEDDED_FILES_CACHE_KEY = 'embeddedFilesCache'\n\nasync function updateEmbeddedFilesCache({\n\tmdxFile,\n\tembeddedFiles,\n}: CodeFileData) {\n\tif (mdxFile.includes('playground')) return\n\tlet cachedList = await getEmbeddedFilesCache()\n\tconst hash = cachedList ? md5(JSON.stringify(cachedList)) : null\n\n\t// make sure we get clean list before updating it\n\tif (cachedList) {\n\t\tfor (const [key, value] of Object.entries(cachedList)) {\n\t\t\tcachedList[key] = value.filter(item => item !== mdxFile)\n\t\t\tif (cachedList[key]?.length === 0) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete cachedList[key]\n\t\t\t}\n\t\t}\n\t}\n\n\tif (embeddedFiles.size) {\n\t\tif (!cachedList) {\n\t\t\tcachedList = {}\n\t\t}\n\t\tconst files = Array.from(\n\t\t\tnew Set(Array.from(embeddedFiles.values()).map(({ file }) => file)),\n\t\t).sort()\n\t\tfor (const file of files) {\n\t\t\tcachedList[file] = [...(cachedList[file] ?? []), mdxFile]\n\t\t}\n\t}\n\n\tif (cachedList && hash !== md5(JSON.stringify(cachedList))) {\n\t\tawait fsExtra.ensureDir(cacheDir)\n\t\tconst embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json')\n\t\tmodifiedEmbeddedFilesTime.set(EMBEDDED_FILES_CACHE_KEY, Date.now())\n\t\tawait fs.promises.writeFile(\n\t\t\tembeddedFilesLocation,\n\t\t\tJSON.stringify({ ...cachedList }),\n\t\t)\n\t}\n}\n\nasync function getEmbeddedFilesCache() {\n\tconst key = EMBEDDED_FILES_CACHE_KEY\n\n\tfunction getForceFresh(cacheEntry: CacheEntry | null | undefined) {\n\t\tif (!cacheEntry) return true\n\t\tconst latestModifiedTime = modifiedEmbeddedFilesTime.get(key)\n\t\tif (!latestModifiedTime) return undefined\n\t\treturn latestModifiedTime > cacheEntry.metadata.createdTime\n\t\t\t? true\n\t\t\t: undefined\n\t}\n\n\treturn cachified({\n\t\tkey,\n\t\tcache: embeddedFilesCache,\n\t\tttl: 1000 * 60 * 60 * 24,\n\t\tforceFresh: getForceFresh(embeddedFilesCache.get(key)),\n\t\tgetFreshValue: async () => {\n\t\t\ttry {\n\t\t\t\tconst embeddedFilesLocation = path.join(cacheDir, 'embeddedFiles.json')\n\t\t\t\tif (await checkFileExists(embeddedFilesLocation)) {\n\t\t\t\t\treturn JSON.parse(\n\t\t\t\t\t\tawait fs.promises.readFile(embeddedFilesLocation, 'utf-8'),\n\t\t\t\t\t) as CachedEmbeddedFilesList\n\t\t\t\t}\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconsole.error(`Unable to read 'embeddedFiles.json' from: `, cacheDir)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t})\n}\n\nexport async function isEmbeddedFile(filePath: string) {\n\tif (process.env.NODE_ENV !== 'development') return false\n\tconst embeddedFilesList = await getEmbeddedFilesCache()\n\tif (embeddedFilesList) {\n\t\tconst embeddedFiles = Object.keys(embeddedFilesList)\n\t\treturn embeddedFiles.includes(filePath.replace(/\\\\/g, '/'))\n\t}\n\treturn false\n}\n\nlet _queue: PQueue | null = null\nasync function getQueue() {\n\tif (_queue) return _queue\n\n\t_queue = new PQueue({\n\t\tconcurrency: 1,\n\t\tthrowOnTimeout: true,\n\t\ttimeout: 1000 * 60,\n\t})\n\treturn _queue\n}\n\n// We have to use a queue because we can't run more than one of these at a time\n// or we'll hit an out of memory error because esbuild uses a lot of memory...\nasync function queuedBundleMDX(...args: Parameters<typeof bundleMDX>) {\n\tconst queue = await getQueue()\n\tconst result = await queue.add(() => bundleMDX(...args))\n\treturn result\n}\n\n// TODO: Fix these\n/*\neslint\n\t\"@typescript-eslint/no-unsafe-assignment\": \"off\",\n\t\"@typescript-eslint/no-unsafe-member-access\": \"off\",\n\t\"@typescript-eslint/no-unnecessary-condition\": \"off\",\n\t\"@typescript-eslint/no-unsafe-argument\": \"off\",\n*/\n"]}
@@ -0,0 +1,176 @@
1
+ import { z } from 'zod';
2
+ export declare const DiscordMemberSchema: z.ZodObject<{
3
+ avatarURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
4
+ displayName: z.ZodString;
5
+ id: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ id: string;
8
+ displayName: string;
9
+ avatarURL?: string | null | undefined;
10
+ }, {
11
+ id: string;
12
+ displayName: string;
13
+ avatarURL?: string | null | undefined;
14
+ }>;
15
+ declare const TokenSetSchema: z.ZodObject<{
16
+ access_token: z.ZodString;
17
+ token_type: z.ZodString;
18
+ scope: z.ZodString;
19
+ }, "strip", z.ZodTypeAny, {
20
+ access_token: string;
21
+ token_type: string;
22
+ scope: string;
23
+ }, {
24
+ access_token: string;
25
+ token_type: string;
26
+ scope: string;
27
+ }>;
28
+ export declare const PlayerPreferencesSchema: z.ZodDefault<z.ZodOptional<z.ZodObject<{
29
+ volumeRate: z.ZodOptional<z.ZodNumber>;
30
+ playbackRate: z.ZodOptional<z.ZodNumber>;
31
+ autoplay: z.ZodOptional<z.ZodBoolean>;
32
+ subtitle: z.ZodDefault<z.ZodOptional<z.ZodObject<{
33
+ id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
34
+ mode: z.ZodDefault<z.ZodNullable<z.ZodUnion<[z.ZodUnion<[z.ZodLiteral<"disabled">, z.ZodLiteral<"hidden">]>, z.ZodLiteral<"showing">]>>>;
35
+ }, "strip", z.ZodTypeAny, {
36
+ id: string | null;
37
+ mode: "disabled" | "hidden" | "showing" | null;
38
+ }, {
39
+ id?: string | null | undefined;
40
+ mode?: "disabled" | "hidden" | "showing" | null | undefined;
41
+ }>>>;
42
+ muted: z.ZodOptional<z.ZodBoolean>;
43
+ theater: z.ZodOptional<z.ZodBoolean>;
44
+ defaultView: z.ZodOptional<z.ZodString>;
45
+ activeSidebarTab: z.ZodOptional<z.ZodNumber>;
46
+ }, "strip", z.ZodTypeAny, {
47
+ subtitle: {
48
+ id: string | null;
49
+ mode: "disabled" | "hidden" | "showing" | null;
50
+ };
51
+ volumeRate?: number | undefined;
52
+ playbackRate?: number | undefined;
53
+ autoplay?: boolean | undefined;
54
+ muted?: boolean | undefined;
55
+ theater?: boolean | undefined;
56
+ defaultView?: string | undefined;
57
+ activeSidebarTab?: number | undefined;
58
+ }, {
59
+ volumeRate?: number | undefined;
60
+ playbackRate?: number | undefined;
61
+ autoplay?: boolean | undefined;
62
+ subtitle?: {
63
+ id?: string | null | undefined;
64
+ mode?: "disabled" | "hidden" | "showing" | null | undefined;
65
+ } | undefined;
66
+ muted?: boolean | undefined;
67
+ theater?: boolean | undefined;
68
+ defaultView?: string | undefined;
69
+ activeSidebarTab?: number | undefined;
70
+ }>>>;
71
+ declare const PresencePreferencesSchema: z.ZodDefault<z.ZodOptional<z.ZodObject<{
72
+ optOut: z.ZodBoolean;
73
+ }, "strip", z.ZodTypeAny, {
74
+ optOut: boolean;
75
+ }, {
76
+ optOut: boolean;
77
+ }>>>;
78
+ export declare function deleteDb(): Promise<null | undefined>;
79
+ export declare function getAuthInfo(): Promise<{
80
+ id: string;
81
+ tokenSet: {
82
+ access_token: string;
83
+ token_type: string;
84
+ scope: string;
85
+ };
86
+ email: string;
87
+ name?: string | null | undefined;
88
+ } | null>;
89
+ export declare function getUserInfo(): Promise<{
90
+ id: string;
91
+ name: string | null;
92
+ email: string;
93
+ avatarUrl: string;
94
+ } | null>;
95
+ export declare function requireAuthInfo({ request, redirectTo, }: {
96
+ request: Request;
97
+ redirectTo?: string | null;
98
+ }): Promise<{
99
+ id: string;
100
+ tokenSet: {
101
+ access_token: string;
102
+ token_type: string;
103
+ scope: string;
104
+ };
105
+ email: string;
106
+ name?: string | null | undefined;
107
+ }>;
108
+ export declare function setAuthInfo({ tokenSet, email, name, }: {
109
+ tokenSet: Partial<z.infer<typeof TokenSetSchema>>;
110
+ email?: string;
111
+ name?: string;
112
+ }): Promise<{
113
+ id: string;
114
+ tokenSet: {
115
+ access_token: string;
116
+ token_type: string;
117
+ scope: string;
118
+ };
119
+ email: string;
120
+ name?: string | null | undefined;
121
+ }>;
122
+ export declare function getPreferences(): Promise<{
123
+ player: {
124
+ subtitle: {
125
+ id: string | null;
126
+ mode: "disabled" | "hidden" | "showing" | null;
127
+ };
128
+ volumeRate?: number | undefined;
129
+ playbackRate?: number | undefined;
130
+ autoplay?: boolean | undefined;
131
+ muted?: boolean | undefined;
132
+ theater?: boolean | undefined;
133
+ defaultView?: string | undefined;
134
+ activeSidebarTab?: number | undefined;
135
+ };
136
+ presence: {
137
+ optOut: boolean;
138
+ };
139
+ } | null>;
140
+ export declare function setPlayerPreferences(playerPreferences: z.input<typeof PlayerPreferencesSchema>): Promise<{
141
+ volumeRate?: number | undefined;
142
+ playbackRate?: number | undefined;
143
+ autoplay?: boolean | undefined;
144
+ subtitle?: {
145
+ id?: string | null | undefined;
146
+ mode?: "disabled" | "hidden" | "showing" | null | undefined;
147
+ } | undefined;
148
+ muted?: boolean | undefined;
149
+ theater?: boolean | undefined;
150
+ defaultView?: string | undefined;
151
+ activeSidebarTab?: number | undefined;
152
+ } | undefined>;
153
+ export declare function setPresencePreferences(presnecePreferences: z.input<typeof PresencePreferencesSchema>): Promise<{
154
+ optOut: boolean;
155
+ } | undefined>;
156
+ export declare function getDiscordMember(): Promise<{
157
+ id: string;
158
+ displayName: string;
159
+ avatarURL?: string | null | undefined;
160
+ } | null>;
161
+ export declare function setDiscordMember(discordMember: z.infer<typeof DiscordMemberSchema>): Promise<{
162
+ id: string;
163
+ displayName: string;
164
+ avatarURL?: string | null | undefined;
165
+ }>;
166
+ export declare function deleteDiscordInfo(): Promise<void>;
167
+ export declare function readOnboardingData(): Promise<{
168
+ finishedTourVideo: boolean;
169
+ } | null>;
170
+ export declare function updateOnboardingData(onboardingData: {
171
+ finishedTourVideo: boolean;
172
+ }): Promise<{
173
+ finishedTourVideo: boolean;
174
+ }>;
175
+ export {};
176
+ //# sourceMappingURL=db.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.server.d.ts","sourceRoot":"","sources":["../../src/db.server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAA;AAEF,QAAA,MAAM,cAAc;;;;;;;;;;;;EAIlB,CAAA;AACF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAuBvB,CAAA;AAEb,QAAA,MAAM,yBAAyB;;;;;;IAKH,CAAA;AA6B5B,wBAAsB,QAAQ,8BAU7B;AAoBD,wBAAsB,WAAW;;;;;;;;;UAGhC;AAED,wBAAsB,WAAW;;;;;UAYhC;AAaD,wBAAsB,eAAe,CAAC,EACrC,OAAO,EACP,UAAU,GACV,EAAE;IACF,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;;;;;;;;;GAeA;AAED,wBAAsB,WAAW,CAAC,EACjC,QAAQ,EACR,KAA6B,EAC7B,IAAI,GACJ,EAAE;IACF,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC,CAAA;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;;;;;;;;;GAMA;AAED,wBAAsB,cAAc;;;;;;;;;;;;;;;;;UAGnC;AAED,wBAAsB,oBAAoB,CACzC,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC;;;;;;;;;;;;eAU1D;AAED,wBAAsB,sBAAsB,CAC3C,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC;;eAU9D;AAED,wBAAsB,gBAAgB;;;;UAGrC;AAED,wBAAsB,gBAAgB,CACrC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC;;;;GAUlD;AAED,wBAAsB,iBAAiB,kBAKtC;AAED,wBAAsB,kBAAkB;;UAGvC;AAED,wBAAsB,oBAAoB,CAAC,cAAc,EAAE;IAC1D,iBAAiB,EAAE,OAAO,CAAA;CAC1B;uBADmB,OAAO;GAU1B"}