inibase 1.0.0-rc.102 → 1.0.0-rc.104

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.
package/dist/file.d.ts CHANGED
@@ -3,6 +3,7 @@ export declare const lock: (folderPath: string, prefix?: string) => Promise<void
3
3
  export declare const unlock: (folderPath: string, prefix?: string) => Promise<void>;
4
4
  export declare const write: (filePath: string, data: any) => Promise<void>;
5
5
  export declare const read: (filePath: string) => Promise<string>;
6
+ export declare function escapeShellPath(filePath: string): string;
6
7
  /**
7
8
  * Checks if a file or directory exists at the specified path.
8
9
  *
package/dist/file.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { createWriteStream } from "node:fs";
2
2
  import { access, appendFile, copyFile, constants as fsConstants, open, readFile, unlink, writeFile, } from "node:fs/promises";
3
- import { join } from "node:path";
3
+ import { join, resolve } from "node:path";
4
4
  import { createInterface } from "node:readline";
5
5
  import { Transform } from "node:stream";
6
6
  import { pipeline } from "node:stream/promises";
7
7
  import { createGunzip, createGzip } from "node:zlib";
8
+ import { spawn as spawnSync } from "node:child_process";
8
9
  import Inison from "inison";
9
10
  import { detectFieldType, isArrayOfObjects, isStringified, isNumber, isObject, } from "./utils.js";
10
11
  import { compare, encodeID, exec, gunzip, gzip } from "./utils.server.js";
11
- import { spawn } from "node:child_process";
12
12
  export const lock = async (folderPath, prefix) => {
13
13
  let lockFile = null;
14
14
  const lockFilePath = join(folderPath, `${prefix ?? ""}.locked`);
@@ -36,6 +36,12 @@ export const write = async (filePath, data) => {
36
36
  export const read = async (filePath) => filePath.endsWith(".gz")
37
37
  ? (await gunzip(await readFile(filePath, "utf8"))).toString()
38
38
  : await readFile(filePath, "utf8");
39
+ export function escapeShellPath(filePath) {
40
+ // Resolve the path to avoid relative path issues
41
+ const resolvedPath = resolve(filePath);
42
+ // Escape double quotes and special shell characters
43
+ return resolvedPath.replace(/(["\\$`])/g, "\\$1");
44
+ }
39
45
  const _pipeline = async (filePath, rl, writeStream, transform) => {
40
46
  if (filePath.endsWith(".gz"))
41
47
  await pipeline(rl, transform, createGzip(), writeStream);
@@ -194,9 +200,10 @@ export async function get(filePath, lineNumbers, fieldType, fieldChildrenType, s
194
200
  }
195
201
  }
196
202
  else if (lineNumbers == -1) {
203
+ const escapedFilePath = `${escapeShellPath(filePath)}`;
197
204
  const command = filePath.endsWith(".gz")
198
- ? `zcat ${filePath} | sed -n '$p'`
199
- : `sed -n '$p' ${filePath}`, foundedLine = (await exec(command)).stdout.trimEnd();
205
+ ? `zcat ${escapedFilePath} | sed -n '$p'`
206
+ : `sed -n '$p' ${escapedFilePath}`, foundedLine = (await exec(command)).stdout.trimEnd();
200
207
  if (foundedLine)
201
208
  lines[linesCount] = decode(foundedLine, fieldType, fieldChildrenType, secretKey);
202
209
  }
@@ -215,9 +222,10 @@ export async function get(filePath, lineNumbers, fieldType, fieldChildrenType, s
215
222
  }
216
223
  return [lines, linesCount];
217
224
  }
225
+ const escapedFilePath = `${escapeShellPath(filePath)}`;
218
226
  const command = filePath.endsWith(".gz")
219
- ? `zcat ${filePath} | sed -n '${lineNumbers.join("p;")}p'`
220
- : `sed -n '${lineNumbers.join("p;")}p' ${filePath}`, foundedLines = (await exec(command)).stdout.trimEnd().split("\n");
227
+ ? `zcat "${escapedFilePath}" | sed -n '${lineNumbers.join("p;")}p'`
228
+ : `sed -n '${lineNumbers.join("p;")}p' "${escapedFilePath}"`, foundedLines = (await exec(command)).stdout.trimEnd().split("\n");
221
229
  let index = 0;
222
230
  for (const line of foundedLines) {
223
231
  lines[lineNumbers[index]] = decode(line, fieldType, fieldChildrenType, secretKey);
@@ -278,7 +286,7 @@ export const replace = async (filePath, replacements, totalItems) => {
278
286
  }
279
287
  else {
280
288
  return new Promise((resolve) => {
281
- const sedProcess = spawn("sed", [
289
+ const sedProcess = spawnSync("sed", [
282
290
  "-e",
283
291
  `s/.*/${replacements}/`,
284
292
  "-e",
@@ -347,9 +355,10 @@ export const append = async (filePath, data) => {
347
355
  await appendFile(fileTempPath, `${Array.isArray(data) ? data.join("\n") : data}\n`);
348
356
  }
349
357
  else {
358
+ const escapedFileTempPath = `${escapeShellPath(fileTempPath)}`;
350
359
  await exec(`echo $'${(Array.isArray(data) ? data.join("\n") : data)
351
360
  .toString()
352
- .replace(/'/g, "\\'")}' | gzip - >> ${fileTempPath}`);
361
+ .replace(/'/g, "\\'")}' | gzip - >> ${escapedFileTempPath}`);
353
362
  }
354
363
  }
355
364
  else
@@ -402,7 +411,10 @@ export const prepend = async (filePath, data) => {
402
411
  const fileChildTempPath = filePath.replace(/([^/]+)\/?$/, ".tmp/tmp_$1");
403
412
  try {
404
413
  await write(fileChildTempPath, `${Array.isArray(data) ? data.join("\n") : data}\n`);
405
- await exec(`cat ${fileChildTempPath} ${filePath} > ${fileTempPath}`);
414
+ const escapedFilePath = `${escapeShellPath(filePath)}`;
415
+ const escapedFileTempPath = `${escapeShellPath(fileTempPath)}`;
416
+ const escapedFileChildTempPath = `${escapeShellPath(fileChildTempPath)}`;
417
+ await exec(`cat ${escapedFileChildTempPath} ${escapedFilePath} > ${escapedFileTempPath}`);
406
418
  }
407
419
  catch {
408
420
  return [fileTempPath, null];
@@ -439,9 +451,11 @@ export const remove = async (filePath, linesToDelete) => {
439
451
  throw new Error("UNVALID_LINE_NUMBERS");
440
452
  const fileTempPath = filePath.replace(/([^/]+)\/?$/, ".tmp/$1");
441
453
  try {
454
+ const escapedFilePath = `${escapeShellPath(filePath)}`;
455
+ const escapedFileTempPath = `${escapeShellPath(fileTempPath)}`;
442
456
  const command = filePath.endsWith(".gz")
443
- ? `zcat ${filePath} | sed "${linesToDelete.join("d;")}d" | gzip > ${fileTempPath}`
444
- : `sed "${linesToDelete.join("d;")}d" ${filePath} > ${fileTempPath}`;
457
+ ? `zcat ${escapedFilePath} | sed "${linesToDelete.join("d;")}d" | gzip > ${fileTempPath}`
458
+ : `sed "${linesToDelete.join("d;")}d" ${escapedFilePath} > ${escapedFileTempPath}`;
445
459
  await exec(command);
446
460
  return [fileTempPath, filePath];
447
461
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.102",
3
+ "version": "1.0.0-rc.104",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Karim Amahtil",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "description": "A file-based & memory-efficient, serverless, ACID compliant, relational database management system",
21
21
  "engines": {
22
- "node": ">=16"
22
+ "node": ">=22"
23
23
  },
24
24
  "files": [
25
25
  "/dist"