@mxpicture/print-backlog 0.0.5 → 0.0.7

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 (46) hide show
  1. package/dist/public/assets/index-C4BbRvDB.js +1 -0
  2. package/dist/public/assets/index-D7yzmKDn.css +1 -0
  3. package/dist/public/index.html +2 -2
  4. package/dist/server/api/events.d.ts +21 -0
  5. package/dist/server/api/events.d.ts.map +1 -0
  6. package/dist/server/api/events.js +201 -0
  7. package/dist/server/api/events.js.map +1 -0
  8. package/dist/server/api/items.d.ts +24 -1
  9. package/dist/server/api/items.d.ts.map +1 -1
  10. package/dist/server/api/items.js +181 -9
  11. package/dist/server/api/items.js.map +1 -1
  12. package/dist/server/app.d.ts +7 -1
  13. package/dist/server/app.d.ts.map +1 -1
  14. package/dist/server/app.js +11 -5
  15. package/dist/server/app.js.map +1 -1
  16. package/dist/server/bambuddy.d.ts +23 -6
  17. package/dist/server/bambuddy.d.ts.map +1 -1
  18. package/dist/server/bambuddy.js +95 -23
  19. package/dist/server/bambuddy.js.map +1 -1
  20. package/dist/server/cli.js +8 -1
  21. package/dist/server/cli.js.map +1 -1
  22. package/dist/server/matching.d.ts +22 -0
  23. package/dist/server/matching.d.ts.map +1 -0
  24. package/dist/server/matching.js +72 -0
  25. package/dist/server/matching.js.map +1 -0
  26. package/dist/server/multipart.d.ts +3 -1
  27. package/dist/server/multipart.d.ts.map +1 -1
  28. package/dist/server/multipart.js +2 -2
  29. package/dist/server/multipart.js.map +1 -1
  30. package/dist/server/storage.d.ts +18 -4
  31. package/dist/server/storage.d.ts.map +1 -1
  32. package/dist/server/storage.js +32 -3
  33. package/dist/server/storage.js.map +1 -1
  34. package/dist/server/zip.d.ts +35 -0
  35. package/dist/server/zip.d.ts.map +1 -0
  36. package/dist/server/zip.js +190 -0
  37. package/dist/server/zip.js.map +1 -0
  38. package/dist/shared/types.d.ts +46 -0
  39. package/dist/shared/types.d.ts.map +1 -1
  40. package/package.json +7 -1
  41. package/dist/public/assets/index-CLP1jBWd.js +0 -1
  42. package/dist/public/assets/index-DxpzozYw.css +0 -1
  43. package/dist/server/api/hooks.d.ts +0 -9
  44. package/dist/server/api/hooks.d.ts.map +0 -1
  45. package/dist/server/api/hooks.js +0 -29
  46. package/dist/server/api/hooks.js.map +0 -1
@@ -49,7 +49,14 @@ const serve = async () => {
49
49
  ? setInterval(() => void checkBambuddy(), BAMBUDDY_CHECK_MS)
50
50
  : null;
51
51
  const staticDir = fileURLToPath(new URL("../public/", import.meta.url));
52
- const router = buildRouter({ sql, store, bambuddy });
52
+ const router = buildRouter({
53
+ sql,
54
+ store,
55
+ bambuddy,
56
+ sender: client && config.bambuddy
57
+ ? { client, folder: config.bambuddy.folder }
58
+ : null,
59
+ });
53
60
  const server = createServer((req, res) => void handle(req, res, {
54
61
  origin: config.origin,
55
62
  userHeader: config.userHeader,
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/server/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/server/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { ItemStatus } from "../shared/types.js";
2
+ /**
3
+ * A name reduced to what survives slicing and Bambuddy's cleaning: lower
4
+ * case, no extension, no trailing plate number, `_ - .` as spaces, accents
5
+ * dropped, whitespace collapsed.
6
+ */
7
+ export declare const norm: (s: string) => string;
8
+ export interface Candidate {
9
+ id: number;
10
+ title: string;
11
+ /** file names of every version of the item */
12
+ filenames: string[];
13
+ }
14
+ /** The candidates whose title or any version's file name matches `filename`. */
15
+ export declare const matchCandidates: <C extends Candidate>(filename: string | null | undefined, candidates: readonly C[]) => C[];
16
+ /** Bambuddy's webhook events we act on. */
17
+ export type PrintEvent = "print_complete" | "print_failed" | "print_stopped";
18
+ /** The status a matched print sets, or null when it changes nothing (a cancelled print). */
19
+ export declare const statusForEvent: (event: string) => ItemStatus | null;
20
+ /** The fields of the webhook payload kept with the status change (`detail`). */
21
+ export declare const eventDetail: (payload: Record<string, unknown>) => Record<string, unknown>;
22
+ //# sourceMappingURL=matching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/server/matching.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAsBrD;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MAahC,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,gFAAgF;AAChF,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,SAAS,EACjD,UAAU,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,YAAY,SAAS,CAAC,EAAE,KACvB,CAAC,EAMH,CAAC;AAEF,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,cAAc,GAAG,eAAe,CAAC;AAE7E,4FAA4F;AAC5F,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,UAAU,GAAG,IAI3D,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,MAAM,CAAC,MAAM,EAAE,OAAO,CAiBxB,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Matching a Bambuddy print event to a backlog item (docs/plan.md §3.9).
3
+ * Pure functions: the database side is in api/events.ts.
4
+ *
5
+ * Bambuddy's webhook `filename` is the slicer project name with `_` replaced
6
+ * by spaces, or else the printed file's name without `.gcode` / `.gcode.3mf`
7
+ * / `.3mf`. Without server-side slicing nothing links the printed file to
8
+ * our upload, so the match is by name, and only an exact one counts.
9
+ */
10
+ const MODEL_SUFFIXES = [
11
+ ".gcode.3mf",
12
+ ".3mf",
13
+ ".stl",
14
+ ".step",
15
+ ".stp",
16
+ ".obj",
17
+ ".gcode",
18
+ ];
19
+ /**
20
+ * A name reduced to what survives slicing and Bambuddy's cleaning: lower
21
+ * case, no extension, no trailing plate number, `_ - .` as spaces, accents
22
+ * dropped, whitespace collapsed.
23
+ */
24
+ export const norm = (s) => {
25
+ let n = s.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().trim();
26
+ for (let changed = true; changed;) {
27
+ changed = false;
28
+ for (const suffix of MODEL_SUFFIXES)
29
+ if (n.endsWith(suffix)) {
30
+ n = n.slice(0, -suffix.length);
31
+ changed = true;
32
+ }
33
+ }
34
+ n = n.replace(/[_\-.]+/g, " ");
35
+ n = n.replace(/\s+plate\s*\d+$/, "");
36
+ return n.replace(/\s+/g, " ").trim();
37
+ };
38
+ /** The candidates whose title or any version's file name matches `filename`. */
39
+ export const matchCandidates = (filename, candidates) => {
40
+ const key = norm(filename ?? "");
41
+ if (!key)
42
+ return [];
43
+ return candidates.filter((c) => norm(c.title) === key || c.filenames.some((f) => norm(f) === key));
44
+ };
45
+ /** The status a matched print sets, or null when it changes nothing (a cancelled print). */
46
+ export const statusForEvent = (event) => {
47
+ if (event === "print_complete")
48
+ return "done";
49
+ if (event === "print_failed")
50
+ return "error";
51
+ return null;
52
+ };
53
+ /** The fields of the webhook payload kept with the status change (`detail`). */
54
+ export const eventDetail = (payload) => {
55
+ const keep = [
56
+ "printer",
57
+ "filename",
58
+ "duration",
59
+ "filament_grams",
60
+ "reason",
61
+ "status",
62
+ ];
63
+ const out = {};
64
+ for (const k of keep) {
65
+ const v = payload[k];
66
+ // Bambuddy fills unknown values with "Unknown"; leave those out.
67
+ if (v !== undefined && v !== null && v !== "" && v !== "Unknown")
68
+ out[k] = v;
69
+ }
70
+ return out;
71
+ };
72
+ //# sourceMappingURL=matching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matching.js","sourceRoot":"","sources":["../../src/server/matching.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,MAAM,cAAc,GAAG;IACrB,YAAY;IACZ,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,QAAQ;CACT,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE;IACxC,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACxE,KAAK,IAAI,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,CAAC;QAClC,OAAO,GAAG,KAAK,CAAC;QAChB,KAAK,MAAM,MAAM,IAAI,cAAc;YACjC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/B,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;IACL,CAAC;IACD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACvC,CAAC,CAAC;AASF,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,QAAmC,EACnC,UAAwB,EACnB,EAAE;IACP,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO,UAAU,CAAC,MAAM,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CACzE,CAAC;AACJ,CAAC,CAAC;AAKF,4FAA4F;AAC5F,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAqB,EAAE;IACjE,IAAI,KAAK,KAAK,gBAAgB;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,KAAK,KAAK,cAAc;QAAE,OAAO,OAAO,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,OAAgC,EACP,EAAE;IAC3B,MAAM,IAAI,GAAG;QACX,SAAS;QACT,UAAU;QACV,UAAU;QACV,gBAAgB;QAChB,QAAQ;QACR,QAAQ;KACT,CAAC;IACF,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,iEAAiE;QACjE,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,SAAS;YAC9D,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
@@ -11,5 +11,7 @@ export declare const MAX_FILES = 50;
11
11
  * (streamed, hashed, size-capped), every other part is a text field. On any
12
12
  * error the files staged so far are discarded, so nothing is left in .tmp.
13
13
  */
14
- export declare const readMultipart: (req: IncomingMessage, store: FileStore) => Promise<Multipart>;
14
+ export declare const readMultipart: (req: IncomingMessage, store: FileStore, opts?: {
15
+ allowZip?: boolean;
16
+ }) => Promise<Multipart>;
15
17
  //# sourceMappingURL=multipart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAkB,MAAM,cAAc,CAAC;AAE/E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,+EAA+E;AAC/E,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,OAAO,SAAS,KACf,OAAO,CAAC,SAAS,CAyEnB,CAAC"}
1
+ {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAkB,MAAM,cAAc,CAAC;AAE/E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,+EAA+E;AAC/E,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,OAAO,SAAS,EAChB,OAAM;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,KAChC,OAAO,CAAC,SAAS,CA8EnB,CAAC"}
@@ -8,7 +8,7 @@ export const MAX_FILES = 50;
8
8
  * (streamed, hashed, size-capped), every other part is a text field. On any
9
9
  * error the files staged so far are discarded, so nothing is left in .tmp.
10
10
  */
11
- export const readMultipart = async (req, store) => {
11
+ export const readMultipart = async (req, store, opts = {}) => {
12
12
  if (!/^multipart\/form-data\s*;/i.test(req.headers["content-type"] ?? ""))
13
13
  throw new HttpError(415, "an upload must be multipart/form-data");
14
14
  let bb;
@@ -34,7 +34,7 @@ export const readMultipart = async (req, store) => {
34
34
  bb.on("file", (_name, stream, info) => {
35
35
  let truncated = false;
36
36
  stream.on("limit", () => (truncated = true));
37
- const p = store.stage(stream, info.filename ?? "file", () => truncated);
37
+ const p = store.stage(stream, info.filename ?? "file", () => truncated, opts);
38
38
  // Settled later with allSettled; keep an early rejection from being "unhandled".
39
39
  p.catch(() => { });
40
40
  staging.push(p);
@@ -1 +1 @@
1
- {"version":3,"file":"multipart.js","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"multipart.js","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ import type { Readable } from "node:stream";
10
10
  * fails loudly on a rewritten file; this keeps it from ever happening.
11
11
  * - .tmp sits inside files/ so the link stays on one filesystem.
12
12
  */
13
- /** Model formats we keep. ZIP import is planned (unpacks into these). */
13
+ /** Model formats we keep. A ZIP upload is unpacked into these (zip.ts). */
14
14
  export declare const MODEL_EXTENSIONS: readonly ["stl", "3mf", "step", "stp", "obj"];
15
15
  export type ModelExt = (typeof MODEL_EXTENSIONS)[number];
16
16
  /** Formats Bambuddy can take (Send to Bambuddy); STEP it cannot slice. */
@@ -32,14 +32,21 @@ export declare const safeFilename: (name: string) => string;
32
32
  export declare const modelExt: (filename: string) => ModelExt;
33
33
  /** The title a new item gets from its first file: the name without the extension, separators as spaces. */
34
34
  export declare const titleFromFilename: (filename: string) => string;
35
- /** A file received and hashed, waiting in .tmp to be placed. */
35
+ /** A file received and hashed, waiting in .tmp to be placed. `zip` only where the caller allowed it (a new item upload). */
36
36
  export interface StagedFile {
37
37
  tmpPath: string;
38
38
  filename: string;
39
- ext: ModelExt;
39
+ ext: ModelExt | "zip";
40
40
  size: number;
41
41
  sha256: string;
42
42
  }
43
+ /** A staged file that is a model, not a ZIP still to unpack. */
44
+ export type StagedModel = StagedFile & {
45
+ ext: ModelExt;
46
+ };
47
+ export declare const isModel: (f: StagedFile) => f is StagedModel;
48
+ /** modelExt, plus `.zip` when allowed. */
49
+ export declare const uploadExt: (filename: string, allowZip: boolean) => ModelExt | "zip";
43
50
  export declare class FileStore {
44
51
  readonly maxBytes: number;
45
52
  readonly root: string;
@@ -51,11 +58,18 @@ export declare class FileStore {
51
58
  * the name is not a model file or the stream exceeds maxBytes; `truncated`
52
59
  * is busboy's flag for a file cut off at its fileSize limit.
53
60
  */
54
- stage(stream: Readable, rawName: string, truncated: () => boolean): Promise<StagedFile>;
61
+ stage(stream: Readable, rawName: string, truncated: () => boolean, opts?: {
62
+ allowZip?: boolean;
63
+ }): Promise<StagedFile>;
55
64
  /** The path, relative to the store root, a version is stored at. */
56
65
  static relativePath(itemId: number, n: number, sha256: string, filename: string): string;
57
66
  /** Place a staged file at its final path, write-once (EEXIST if anything is there). */
58
67
  place(staged: StagedFile, relPath: string): Promise<void>;
68
+ /**
69
+ * Write a small buffer (a thumbnail) write-once at relPath: through .tmp
70
+ * and link(), like an upload, so EEXIST protects it the same way.
71
+ */
72
+ placeBuffer(data: Buffer, relPath: string): Promise<void>;
59
73
  /** Drop a staged file that will not be placed (duplicate, rejected batch, failed transaction). */
60
74
  discard(staged: StagedFile): Promise<void>;
61
75
  absolute(relPath: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/server/storage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;;;;GAUG;AAEH,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,+CAAgD,CAAC;AAC9E,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAIlD,CAAC;AAEH,qBAAa,cAAe,SAAQ,KAAK;IAErC,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;gBAAjB,MAAM,EAAE,GAAG,GAAG,GAAG,EAC1B,OAAO,EAAE,MAAM;CAIlB;AAID;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAY3C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,KAAG,QAe3C,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,KAAG,MAKpD,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,QAAQ,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,SAAS;IAMlB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAL3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,OAAO,EAAE,MAAM,EACN,QAAQ,EAAE,MAAM;IAMrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B;;;;OAIG;IACG,KAAK,CACT,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,OAAO,GACvB,OAAO,CAAC,UAAU,CAAC;IA2CtB,oEAAoE;IACpE,MAAM,CAAC,YAAY,CACjB,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM;IAIT,uFAAuF;IACjF,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D,kGAAkG;IAC5F,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAO3B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ/C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;CAGhC"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/server/storage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,+CAAgD,CAAC;AAC9E,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAIlD,CAAC;AAEH,qBAAa,cAAe,SAAQ,KAAK;IAErC,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;gBAAjB,MAAM,EAAE,GAAG,GAAG,GAAG,EAC1B,OAAO,EAAE,MAAM;CAIlB;AAID;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAY3C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,KAAG,QAe3C,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,KAAG,MAKpD,CAAC;AAEF,4HAA4H;AAC5H,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,QAAQ,GAAG,KAAK,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,CAAC;AACzD,eAAO,MAAM,OAAO,GAAI,GAAG,UAAU,KAAG,CAAC,IAAI,WAA8B,CAAC;AAE5E,0CAA0C;AAC1C,eAAO,MAAM,SAAS,GACpB,UAAU,MAAM,EAChB,UAAU,OAAO,KAChB,QAAQ,GAAG,KAGb,CAAC;AAEF,qBAAa,SAAS;IAMlB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAL3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,OAAO,EAAE,MAAM,EACN,QAAQ,EAAE,MAAM;IAMrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B;;;;OAIG;IACG,KAAK,CACT,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,OAAO,EACxB,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAO,GAChC,OAAO,CAAC,UAAU,CAAC;IA2CtB,oEAAoE;IACpE,MAAM,CAAC,YAAY,CACjB,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM;IAIT,uFAAuF;IACjF,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB/D,kGAAkG;IAC5F,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAO3B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ/C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;CAGhC"}
@@ -13,7 +13,7 @@ import { dirname, join } from "node:path";
13
13
  * fails loudly on a rewritten file; this keeps it from ever happening.
14
14
  * - .tmp sits inside files/ so the link stays on one filesystem.
15
15
  */
16
- /** Model formats we keep. ZIP import is planned (unpacks into these). */
16
+ /** Model formats we keep. A ZIP upload is unpacked into these (zip.ts). */
17
17
  export const MODEL_EXTENSIONS = ["stl", "3mf", "step", "stp", "obj"];
18
18
  /** Formats Bambuddy can take (Send to Bambuddy); STEP it cannot slice. */
19
19
  export const BAMBUDDY_EXTENSIONS = new Set([
@@ -68,6 +68,13 @@ export const titleFromFilename = (filename) => {
68
68
  const title = stem.replace(/[_]+/g, " ").replace(/\s+/g, " ").trim();
69
69
  return title || filename;
70
70
  };
71
+ export const isModel = (f) => f.ext !== "zip";
72
+ /** modelExt, plus `.zip` when allowed. */
73
+ export const uploadExt = (filename, allowZip) => {
74
+ if (allowZip && filename.toLowerCase().endsWith(".zip"))
75
+ return "zip";
76
+ return modelExt(filename);
77
+ };
71
78
  export class FileStore {
72
79
  maxBytes;
73
80
  root;
@@ -85,11 +92,11 @@ export class FileStore {
85
92
  * the name is not a model file or the stream exceeds maxBytes; `truncated`
86
93
  * is busboy's flag for a file cut off at its fileSize limit.
87
94
  */
88
- async stage(stream, rawName, truncated) {
95
+ async stage(stream, rawName, truncated, opts = {}) {
89
96
  const filename = safeFilename(rawName);
90
97
  let ext;
91
98
  try {
92
- ext = modelExt(filename);
99
+ ext = uploadExt(filename, opts.allowZip ?? false);
93
100
  }
94
101
  catch (e) {
95
102
  stream.resume(); // drain, so busboy moves on to the next part
@@ -145,6 +152,28 @@ export class FileStore {
145
152
  await dir.close();
146
153
  }
147
154
  }
155
+ /**
156
+ * Write a small buffer (a thumbnail) write-once at relPath: through .tmp
157
+ * and link(), like an upload, so EEXIST protects it the same way.
158
+ */
159
+ async placeBuffer(data, relPath) {
160
+ const tmpPath = join(this.tmpDir, randomUUID());
161
+ const fh = await open(tmpPath, "wx", 0o640);
162
+ try {
163
+ await fh.write(data);
164
+ await fh.sync();
165
+ }
166
+ finally {
167
+ await fh.close();
168
+ }
169
+ try {
170
+ await this.place({ tmpPath, filename: "", ext: "stl", size: data.length, sha256: "" }, relPath);
171
+ }
172
+ catch (e) {
173
+ await unlink(tmpPath).catch(() => { });
174
+ throw e;
175
+ }
176
+ }
148
177
  /** Drop a staged file that will not be placed (duplicate, rejected batch, failed transaction). */
149
178
  async discard(staged) {
150
179
  await unlink(staged.tmpPath).catch(() => { });
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/server/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;GAUG;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAG9E,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC,CAAC;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAE5B;IADX,YACW,MAAiB,EAC1B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,WAAM,GAAN,MAAM,CAAW;IAI5B,CAAC;CACF;AAED,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAU,EAAE;IACnD,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,0DAA0D;IAC1D,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3D,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,IAAI,CAAC,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,IAAI,MAAM,CAAC;AACrB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAgB,EAAY,EAAE;IACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC1D,MAAM,IAAI,cAAc,CACtB,GAAG,EACH,GAAG,QAAQ,gDAAgD,CAC5D,CAAC;IACJ,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,IAAK,gBAAsC,CAAC,QAAQ,CAAC,GAAG,CAAC;QACvD,OAAO,GAAe,CAAC;IACzB,MAAM,IAAI,cAAc,CACtB,GAAG,EACH,GAAG,QAAQ,iCAAiC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC/F,CAAC;AACJ,CAAC,CAAC;AAEF,2GAA2G;AAC3G,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAU,EAAE;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,OAAO,KAAK,IAAI,QAAQ,CAAC;AAC3B,CAAC,CAAC;AAWF,MAAM,OAAO,SAAS;IAMT;IALF,IAAI,CAAS;IACb,MAAM,CAAS;IAExB,YACE,OAAe,EACN,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAEzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CACT,MAAgB,EAChB,OAAe,EACf,SAAwB;QAExB,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,6CAA6C;YAC9D,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,mEAAmE;YACnE,uEAAuE;YACvE,4DAA4D;YAC5D,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAA+B,EAAE,CAAC;gBAC1D,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;gBACrB,IAAI,MAAM,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACnC,MAAM,GAAG,IAAI,CAAC;oBACd,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACnB,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,MAAM,IAAI,SAAS,EAAE;gBACvB,MAAM,IAAI,cAAc,CACtB,GAAG,EACH,GAAG,QAAQ,iBAAiB,IAAI,CAAC,QAAQ,QAAQ,CAClD,CAAC;YACJ,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAC,YAAY,CACjB,MAAc,EACd,CAAS,EACT,MAAc,EACd,QAAgB;QAEhB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,KAAK,CAAC,MAAkB,EAAE,OAAe;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnC,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7B,gDAAgD;QAChD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,KAAK,CAAC,OAAO,CAAC,MAAkB;QAC9B,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,QAAQ,CAAC,OAAe;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;QACxD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;CACF"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/server/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAG9E,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC,CAAC;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAE5B;IADX,YACW,MAAiB,EAC1B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,WAAM,GAAN,MAAM,CAAW;IAI5B,CAAC;CACF;AAED,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAU,EAAE;IACnD,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,0DAA0D;IAC1D,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3D,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,IAAI,CAAC,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,IAAI,MAAM,CAAC;AACrB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAgB,EAAY,EAAE;IACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC1D,MAAM,IAAI,cAAc,CACtB,GAAG,EACH,GAAG,QAAQ,gDAAgD,CAC5D,CAAC;IACJ,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,IAAK,gBAAsC,CAAC,QAAQ,CAAC,GAAG,CAAC;QACvD,OAAO,GAAe,CAAC;IACzB,MAAM,IAAI,cAAc,CACtB,GAAG,EACH,GAAG,QAAQ,iCAAiC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC/F,CAAC;AACJ,CAAC,CAAC;AAEF,2GAA2G;AAC3G,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAU,EAAE;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,OAAO,KAAK,IAAI,QAAQ,CAAC;AAC3B,CAAC,CAAC;AAaF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAa,EAAoB,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC;AAE5E,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,QAAgB,EAChB,QAAiB,EACC,EAAE;IACpB,IAAI,QAAQ,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,OAAO,SAAS;IAMT;IALF,IAAI,CAAS;IACb,MAAM,CAAS;IAExB,YACE,OAAe,EACN,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAEzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CACT,MAAgB,EAChB,OAAe,EACf,SAAwB,EACxB,OAA+B,EAAE;QAEjC,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,GAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,GAAG,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,6CAA6C;YAC9D,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,mEAAmE;YACnE,uEAAuE;YACvE,4DAA4D;YAC5D,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAA+B,EAAE,CAAC;gBAC1D,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;gBACrB,IAAI,MAAM,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACnC,MAAM,GAAG,IAAI,CAAC;oBACd,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACnB,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,MAAM,IAAI,SAAS,EAAE;gBACvB,MAAM,IAAI,cAAc,CACtB,GAAG,EACH,GAAG,QAAQ,iBAAiB,IAAI,CAAC,QAAQ,QAAQ,CAClD,CAAC;YACJ,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAC,YAAY,CACjB,MAAc,EACd,CAAS,EACT,MAAc,EACd,QAAgB;QAEhB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,KAAK,CAAC,MAAkB,EAAE,OAAe;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnC,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7B,gDAAgD;QAChD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,OAAe;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACrB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CACd,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EACpE,OAAO,CACR,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,KAAK,CAAC,OAAO,CAAC,MAAkB;QAC9B,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,QAAQ,CAAC,OAAe;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;QACxD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ import type { Readable } from "node:stream";
2
+ import { type FileStore, type StagedFile, type StagedModel } from "./storage.js";
3
+ export interface Unpacked {
4
+ models: StagedModel[];
5
+ /** entries that were not imported (not a model file, sliced, hidden) */
6
+ skipped: string[];
7
+ }
8
+ /**
9
+ * Stage every model file in a staged ZIP; the ZIP itself is discarded.
10
+ * - Each entry goes through store.stage, so the size cap holds per entry
11
+ * (a ZIP bomb stops at maxBytes) and the name is sanitised (the entry's
12
+ * path is dropped; only its base name is kept).
13
+ * - At most `maxModels` models; a ZIP without any model is refused.
14
+ * On any error the models staged so far are discarded.
15
+ */
16
+ export declare const unpackZip: (store: FileStore, zipFile: StagedFile, maxModels: number) => Promise<Unpacked>;
17
+ /**
18
+ * The preview PNG embedded in a 3MF, or null. Never throws: a 3MF without
19
+ * a usable preview (or not a valid ZIP at all) just has no thumbnail.
20
+ */
21
+ export declare const extract3mfThumbnail: (path: string) => Promise<Buffer | null>;
22
+ /** A name that is unique within one export ZIP: "a.stl", "a (2).stl", … */
23
+ export declare const uniqueName: (taken: Set<string>, name: string) => string;
24
+ export interface ExportEntry {
25
+ name: string;
26
+ relPath: string;
27
+ ext: string;
28
+ mtime: Date;
29
+ }
30
+ /**
31
+ * A ZIP of the given files, as a stream, built while it is sent. 3MF is a
32
+ * ZIP already, so it is stored; everything else is deflated.
33
+ */
34
+ export declare const exportZip: (store: FileStore, files: ExportEntry[]) => Readable;
35
+ //# sourceMappingURL=zip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../src/server/zip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,UAAU,EACf,KAAK,WAAW,EAEjB,MAAM,cAAc,CAAC;AAiFtB,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,wEAAwE;IACxE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GACpB,OAAO,SAAS,EAChB,SAAS,UAAU,EACnB,WAAW,MAAM,KAChB,OAAO,CAAC,QAAQ,CA8ClB,CAAC;AAeF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,MAAM,KACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAgCvB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,UAAU,GAAI,OAAO,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,KAAG,MAS7D,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,IAAI,CAAC;CACb;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,SAAS,EAAE,OAAO,WAAW,EAAE,KAAG,QAWlE,CAAC"}
@@ -0,0 +1,190 @@
1
+ import { posix } from "node:path";
2
+ import yauzl from "yauzl";
3
+ import yazl from "yazl";
4
+ import { MODEL_EXTENSIONS, UploadRejected, } from "./storage.js";
5
+ /**
6
+ * ZIP in both directions (docs/plan.md §3.5, §3.6):
7
+ * - unpack a dropped ZIP into model files (one item each);
8
+ * - pull the preview PNG out of a 3MF (a 3MF is a ZIP);
9
+ * - stream a queue's current versions out as one ZIP.
10
+ */
11
+ const openZip = (path) => new Promise((resolve, reject) => yauzl.open(path,
12
+ // lazyEntries: we ask for the next entry; validateEntrySizes: a ZIP that
13
+ // lies about an entry's size errors instead of inflating past it.
14
+ {
15
+ lazyEntries: true,
16
+ autoClose: false,
17
+ validateEntrySizes: true,
18
+ strictFileNames: false,
19
+ }, (err, zip) => err || !zip
20
+ ? reject(err ?? new Error("cannot open zip"))
21
+ : resolve(zip)));
22
+ const openEntry = (zip, entry) => new Promise((resolve, reject) => zip.openReadStream(entry, (err, stream) => err || !stream
23
+ ? reject(err ?? new Error("cannot read entry"))
24
+ : resolve(stream)));
25
+ /** Every entry, in order, without reading data (the caller opens what it needs before asking for the next). */
26
+ async function* entries(zip) {
27
+ for (;;) {
28
+ const next = await new Promise((resolve, reject) => {
29
+ const onEntry = (e) => {
30
+ cleanup();
31
+ resolve(e);
32
+ };
33
+ const onEnd = () => {
34
+ cleanup();
35
+ resolve(null);
36
+ };
37
+ const onError = (e) => {
38
+ cleanup();
39
+ reject(e);
40
+ };
41
+ const cleanup = () => {
42
+ zip.off("entry", onEntry);
43
+ zip.off("end", onEnd);
44
+ zip.off("error", onError);
45
+ };
46
+ zip.on("entry", onEntry);
47
+ zip.on("end", onEnd);
48
+ zip.on("error", onError);
49
+ zip.readEntry();
50
+ });
51
+ if (!next)
52
+ return;
53
+ yield next;
54
+ }
55
+ }
56
+ /** macOS resource forks, hidden files, directories: never a model. */
57
+ const isJunk = (name) => name.endsWith("/") ||
58
+ name.split("/").some((part) => part.startsWith(".") || part === "__MACOSX");
59
+ const isModelName = (name) => {
60
+ const lower = name.toLowerCase();
61
+ if (lower.endsWith(".gcode.3mf"))
62
+ return false;
63
+ return MODEL_EXTENSIONS.includes(posix.extname(lower).slice(1));
64
+ };
65
+ /**
66
+ * Stage every model file in a staged ZIP; the ZIP itself is discarded.
67
+ * - Each entry goes through store.stage, so the size cap holds per entry
68
+ * (a ZIP bomb stops at maxBytes) and the name is sanitised (the entry's
69
+ * path is dropped; only its base name is kept).
70
+ * - At most `maxModels` models; a ZIP without any model is refused.
71
+ * On any error the models staged so far are discarded.
72
+ */
73
+ export const unpackZip = async (store, zipFile, maxModels) => {
74
+ const models = [];
75
+ const skipped = [];
76
+ let zip = null;
77
+ try {
78
+ try {
79
+ zip = await openZip(zipFile.tmpPath);
80
+ }
81
+ catch (e) {
82
+ throw new UploadRejected(415, `${zipFile.filename}: not a readable ZIP (${e instanceof Error ? e.message : String(e)})`);
83
+ }
84
+ for await (const entry of entries(zip)) {
85
+ const name = entry.fileName;
86
+ if (name.endsWith("/"))
87
+ continue;
88
+ if (isJunk(name) || !isModelName(name)) {
89
+ skipped.push(name);
90
+ continue;
91
+ }
92
+ if (models.length >= maxModels)
93
+ throw new UploadRejected(413, `${zipFile.filename}: more than ${maxModels} model files`);
94
+ const stream = await openEntry(zip, entry);
95
+ const staged = await store.stage(stream, posix.basename(name), () => false);
96
+ models.push(staged);
97
+ }
98
+ if (models.length === 0)
99
+ throw new UploadRejected(415, `${zipFile.filename}: no model file in the ZIP`);
100
+ return { models, skipped };
101
+ }
102
+ catch (e) {
103
+ await Promise.all(models.map((m) => store.discard(m)));
104
+ throw e;
105
+ }
106
+ finally {
107
+ zip?.close();
108
+ await store.discard(zipFile);
109
+ }
110
+ };
111
+ /** Preview images in a 3MF, best first (Bambu Studio / OrcaSlicer, then the 3MF core). */
112
+ const THUMBNAIL_ENTRIES = [
113
+ "Metadata/plate_1.png",
114
+ "Metadata/thumbnail.png",
115
+ "Metadata/plate_1_small.png",
116
+ "Thumbnails/thumbnail.png",
117
+ "Metadata/top_1.png",
118
+ ];
119
+ const MAX_THUMBNAIL_BYTES = 4 * 1024 * 1024;
120
+ const PNG_SIGNATURE = Buffer.from([
121
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
122
+ ]);
123
+ /**
124
+ * The preview PNG embedded in a 3MF, or null. Never throws: a 3MF without
125
+ * a usable preview (or not a valid ZIP at all) just has no thumbnail.
126
+ */
127
+ export const extract3mfThumbnail = async (path) => {
128
+ let zip = null;
129
+ try {
130
+ zip = await openZip(path);
131
+ let best = null;
132
+ let fallback = null;
133
+ for await (const entry of entries(zip)) {
134
+ const rank = THUMBNAIL_ENTRIES.findIndex((n) => n.toLowerCase() === entry.fileName.toLowerCase());
135
+ if (rank >= 0 && (!best || rank < best.rank))
136
+ best = { rank, entry };
137
+ else if (!fallback && /^metadata\/[^/]+\.png$/i.test(entry.fileName))
138
+ fallback = entry;
139
+ }
140
+ const chosen = best?.entry ?? fallback;
141
+ if (!chosen || chosen.uncompressedSize > MAX_THUMBNAIL_BYTES)
142
+ return null;
143
+ // entries() is done, so the ZIP is at its end; openReadStream works on any entry.
144
+ const stream = await openEntry(zip, chosen);
145
+ const chunks = [];
146
+ let size = 0;
147
+ for await (const chunk of stream) {
148
+ size += chunk.length;
149
+ if (size > MAX_THUMBNAIL_BYTES)
150
+ return null;
151
+ chunks.push(chunk);
152
+ }
153
+ const png = Buffer.concat(chunks);
154
+ return png.subarray(0, 8).equals(PNG_SIGNATURE) ? png : null;
155
+ }
156
+ catch {
157
+ return null;
158
+ }
159
+ finally {
160
+ zip?.close();
161
+ }
162
+ };
163
+ /** A name that is unique within one export ZIP: "a.stl", "a (2).stl", … */
164
+ export const uniqueName = (taken, name) => {
165
+ let candidate = name;
166
+ const dot = name.lastIndexOf(".");
167
+ const stem = dot > 0 ? name.slice(0, dot) : name;
168
+ const ext = dot > 0 ? name.slice(dot) : "";
169
+ for (let i = 2; taken.has(candidate.toLowerCase()); i++)
170
+ candidate = `${stem} (${i})${ext}`;
171
+ taken.add(candidate.toLowerCase());
172
+ return candidate;
173
+ };
174
+ /**
175
+ * A ZIP of the given files, as a stream, built while it is sent. 3MF is a
176
+ * ZIP already, so it is stored; everything else is deflated.
177
+ */
178
+ export const exportZip = (store, files) => {
179
+ const out = new yazl.ZipFile();
180
+ const taken = new Set();
181
+ for (const f of files) {
182
+ out.addReadStream(store.read(f.relPath), uniqueName(taken, f.name), {
183
+ compress: f.ext !== "3mf",
184
+ mtime: f.mtime,
185
+ });
186
+ }
187
+ out.end();
188
+ return out.outputStream;
189
+ };
190
+ //# sourceMappingURL=zip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip.js","sourceRoot":"","sources":["../../src/server/zip.ts"],"names":[],"mappings":"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"}