MCPcopy Index your code
hub / github.com/browserless/browserless / append

Method append

src/file-system.ts:36–86  ·  view source on GitHub ↗

* Appends contents to a file-path for persistance. File contents are * encrypted before being saved to disk. Reads happen via the in-memory * lookup of the internal map. Appends to the same path are serialized. * * @param path The filepath to persist contents to * @param newContent A

(
    path: string,
    newContent: string,
    shouldEncode: boolean,
    maxEntries?: number,
  )

Source from the content-addressed store, hash-verified

34 * @returns void
35 */
36 public async append(
37 path: string,
38 newContent: string,
39 shouldEncode: boolean,
40 maxEntries?: number,
41 ): Promise<void> {
42 if (
43 maxEntries !== undefined &&
44 (!Number.isInteger(maxEntries) || maxEntries < 1)
45 ) {
46 throw new Error(
47 `maxEntries must be a positive integer when set, got "${maxEntries}"`,
48 );
49 }
50
51 const prior = this.writeChains.get(path) ?? Promise.resolve();
52 const task = prior.then(async () => {
53 // Work on a copy — read() returns the live cached array, and the
54 // cache must only reflect the new entry once the disk write has
55 // succeeded, or a failed write leaves cache and file diverged.
56 const contents = [...(await this.read(path, shouldEncode))];
57
58 contents.push(newContent);
59 if (maxEntries && contents.length > maxEntries) {
60 contents.splice(0, contents.length - maxEntries);
61 }
62
63 const encoded = shouldEncode
64 ? await encrypt(contents.join('\n'), this.currentAESKey)
65 : contents.join('\n');
66
67 await writeFile(path, encoded.toString());
68 this.fsMap.set(path, contents);
69 await this.recordMtime(path);
70 });
71
72 // Keep the chain alive past failures so one bad write doesn't wedge
73 // every subsequent append to this path.
74 const chain = task.catch(() => undefined);
75 this.writeChains.set(path, chain);
76 // Reclaim the entry once this chain settles — unless a newer append for
77 // the same path has already replaced it — so the map doesn't retain one
78 // resolved promise per distinct path for the life of the process.
79 void chain.finally(() => {
80 if (this.writeChains.get(path) === chain) {
81 this.writeChains.delete(path);
82 }
83 });
84
85 return task;
86 }
87
88 /**
89 * Reads contents from the local map, if any exist and the file hasn't

Callers 2

saveMetricsMethod · 0.80

Calls 4

readMethod · 0.95
recordMtimeMethod · 0.95
encryptFunction · 0.85
getMethod · 0.80

Tested by

no test coverage detected