texlite 0.5.5 → 0.6.5

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 (44) hide show
  1. package/README.md +1 -0
  2. package/dist/client/assets/{BinaryModule-Aj1vLnwf-BsIXahIW.js → BinaryModule-Aj1vLnwf-hZ2K_uyt.js} +1 -1
  3. package/dist/client/assets/{GitDialog-CFzsF7ys.js → GitDialog-s54eAFX6.js} +1 -1
  4. package/dist/client/assets/{HistoryDialog-YPiAOGU_.js → HistoryDialog-DrUnIy0a.js} +1 -1
  5. package/dist/client/assets/{LatexEditor-BX4WLdhS.js → LatexEditor-Y5KfVqQI.js} +20 -20
  6. package/dist/client/assets/PdfPreview-BPKX-qpr.js +1 -0
  7. package/dist/client/assets/{ProjectNavigationDialogs-BZanedGt.js → ProjectNavigationDialogs-CjZX0g7O.js} +1 -1
  8. package/dist/client/assets/{SystemMetricsDialog-DnH4c7Se.js → SystemMetricsDialog-B97Og0La.js} +1 -1
  9. package/dist/client/assets/binary-DCBFVo4B.js +1 -0
  10. package/dist/client/assets/index-5ajAy27z.css +1 -0
  11. package/dist/client/assets/index-CCitTPyj.js +17 -0
  12. package/dist/client/assets/{index-B5iMrEn5.js → index-CQG_gpuU.js} +1 -1
  13. package/dist/client/assets/{plus-B-DG5h4y.js → plus-Bp4_lUor.js} +1 -1
  14. package/dist/client/assets/{spellCheck-4xuNPF_M.js → spellCheck-0f5ZG5IV.js} +3 -3
  15. package/dist/client/index.html +2 -2
  16. package/dist/server/app.js +889 -337
  17. package/dist/server/archive.js +20 -3
  18. package/dist/server/auth.js +13 -2
  19. package/dist/server/collaboration.js +815 -124
  20. package/dist/server/compileArtifacts.js +37 -9
  21. package/dist/server/compiler.js +69 -20
  22. package/dist/server/db.js +6 -0
  23. package/dist/server/environment.js +4 -2
  24. package/dist/server/files.js +172 -25
  25. package/dist/server/git.js +152 -124
  26. package/dist/server/history.js +86 -18
  27. package/dist/server/http.js +26 -0
  28. package/dist/server/index.js +39 -26
  29. package/dist/server/instanceLock.js +137 -0
  30. package/dist/server/latexCompletion.js +23 -1
  31. package/dist/server/latexFormatter.js +4 -2
  32. package/dist/server/processTree.js +31 -0
  33. package/dist/server/projectMutations.js +255 -0
  34. package/dist/server/projectOutline.js +113 -1
  35. package/dist/server/projectSearch.js +6 -0
  36. package/dist/server/routes/compile.js +535 -132
  37. package/dist/server/security.js +61 -1
  38. package/dist/server/synctex.js +11 -2
  39. package/dist/server/zip.js +2 -1
  40. package/package.json +1 -1
  41. package/dist/client/assets/PdfPreview-FQ8oxyUx.js +0 -1
  42. package/dist/client/assets/binary-MtJxbY5b.js +0 -1
  43. package/dist/client/assets/index-CUa7L47p.css +0 -1
  44. package/dist/client/assets/index-DdFlmXqA.js +0 -17
@@ -1,19 +1,23 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { pipeline } from "node:stream/promises";
3
4
  import { ZipFile } from "yazl";
4
- import { sourceRoot } from "./files.js";
5
+ import { assertNoSourceSymlinks, sourceRoot, symbolicLinkError } from "./files.js";
5
6
  export function createProjectArchive(config, projectId) {
6
7
  const root = sourceRoot(config, projectId);
8
+ assertNoSourceSymlinks(config, projectId);
7
9
  const archive = new ZipFile();
8
10
  const addDirectory = (directory, prefix) => {
9
11
  const entries = fs.readdirSync(directory, { withFileTypes: true });
10
12
  if (entries.length === 0 && prefix)
11
13
  archive.addEmptyDirectory(`${prefix}/`);
12
14
  for (const entry of entries) {
13
- if (entry.name === ".git" || entry.isSymbolicLink())
14
- continue;
15
15
  const absolute = path.join(directory, entry.name);
16
16
  const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
17
+ if (entry.isSymbolicLink())
18
+ throw symbolicLinkError(relative);
19
+ if (entry.name === ".git")
20
+ continue;
17
21
  if (entry.isDirectory())
18
22
  addDirectory(absolute, relative);
19
23
  else if (entry.isFile())
@@ -24,3 +28,16 @@ export function createProjectArchive(config, projectId) {
24
28
  archive.end();
25
29
  return archive;
26
30
  }
31
+ /**
32
+ * Materialize an archive before releasing the project read lock.
33
+ *
34
+ * yazl reads added files asynchronously. Returning its output stream directly
35
+ * from a route would therefore release the project lock while the ZIP is
36
+ * still being assembled, allowing a concurrent write to produce a mixed
37
+ * archive. Writing to a private temporary file makes the bytes immutable
38
+ * before the caller starts the HTTP stream.
39
+ */
40
+ export async function writeProjectArchive(config, projectId, destination) {
41
+ const archive = createProjectArchive(config, projectId);
42
+ await pipeline(archive.outputStream, fs.createWriteStream(destination, { mode: 0o600 }));
43
+ }
@@ -11,16 +11,27 @@ export function publicUser(user) {
11
11
  createdAt: user.created_at
12
12
  };
13
13
  }
14
+ const requestUserCache = new WeakMap();
15
+ export function clearCurrentUserCache(request) {
16
+ requestUserCache.delete(request);
17
+ }
14
18
  export function currentUser(request, db) {
19
+ if (requestUserCache.has(request)) {
20
+ return requestUserCache.get(request) ?? null;
21
+ }
15
22
  const token = request.cookies.texlite_session;
16
- if (!token)
23
+ if (!token) {
24
+ requestUserCache.set(request, null);
17
25
  return null;
26
+ }
18
27
  const row = db.prepare(`
19
28
  SELECT u.* FROM sessions s
20
29
  JOIN users u ON u.id = s.user_id
21
30
  WHERE s.id = ? AND s.expires_at > ? AND u.disabled = 0
22
31
  `).get(digestToken(token), new Date().toISOString());
23
- return row ?? null;
32
+ const user = row ?? null;
33
+ requestUserCache.set(request, user);
34
+ return user;
24
35
  }
25
36
  export function requireUser(request, reply, db) {
26
37
  const user = currentUser(request, db);