@gtkx/utils 1.0.0-rc.4 → 1.1.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 (102) hide show
  1. package/README.md +5 -5
  2. package/dist/class/any-class.d.ts +2 -0
  3. package/dist/class/any-class.d.ts.map +1 -1
  4. package/dist/class/any-class.js.map +1 -1
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +0 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/log/index.d.ts +1 -1
  10. package/dist/log/index.d.ts.map +1 -1
  11. package/dist/log/index.js.map +1 -1
  12. package/dist/log/logger.d.ts +1 -1
  13. package/dist/log/logger.d.ts.map +1 -1
  14. package/dist/log/logger.js.map +1 -1
  15. package/dist/map/get-or-insert.d.ts +1 -1
  16. package/dist/map/get-or-insert.d.ts.map +1 -1
  17. package/dist/map/get-or-insert.js.map +1 -1
  18. package/dist/predicate/index.d.ts +0 -4
  19. package/dist/predicate/index.d.ts.map +1 -1
  20. package/dist/predicate/index.js +0 -4
  21. package/dist/predicate/index.js.map +1 -1
  22. package/dist/process/index.d.ts +2 -1
  23. package/dist/process/index.d.ts.map +1 -1
  24. package/dist/process/index.js +2 -1
  25. package/dist/process/index.js.map +1 -1
  26. package/dist/process/install-graceful-shutdown.d.ts +1 -1
  27. package/dist/process/install-graceful-shutdown.d.ts.map +1 -1
  28. package/dist/process/install-graceful-shutdown.js.map +1 -1
  29. package/dist/process/kill-marked-processes.d.ts +4 -0
  30. package/dist/process/kill-marked-processes.d.ts.map +1 -0
  31. package/dist/process/kill-marked-processes.js +38 -0
  32. package/dist/process/kill-marked-processes.js.map +1 -0
  33. package/dist/process/process-guard.d.ts +2 -0
  34. package/dist/process/process-guard.d.ts.map +1 -0
  35. package/dist/process/process-guard.js +16 -0
  36. package/dist/process/process-guard.js.map +1 -0
  37. package/dist/process/resolve-executable.d.ts +2 -1
  38. package/dist/process/resolve-executable.d.ts.map +1 -1
  39. package/dist/process/resolve-executable.js +8 -5
  40. package/dist/process/resolve-executable.js.map +1 -1
  41. package/dist/process/spawn-with-parent-death-signal.d.ts +8 -0
  42. package/dist/process/spawn-with-parent-death-signal.d.ts.map +1 -0
  43. package/dist/process/spawn-with-parent-death-signal.js +50 -0
  44. package/dist/process/spawn-with-parent-death-signal.js.map +1 -0
  45. package/dist/source/escape-reserved.d.ts +3 -0
  46. package/dist/source/escape-reserved.d.ts.map +1 -0
  47. package/dist/source/escape-reserved.js +11 -0
  48. package/dist/source/escape-reserved.js.map +1 -0
  49. package/dist/source/index.d.ts +1 -0
  50. package/dist/source/index.d.ts.map +1 -1
  51. package/dist/source/index.js +1 -0
  52. package/dist/source/index.js.map +1 -1
  53. package/dist/source/sanitize-identifier.d.ts +2 -1
  54. package/dist/source/sanitize-identifier.d.ts.map +1 -1
  55. package/dist/source/sanitize-identifier.js +4 -2
  56. package/dist/source/sanitize-identifier.js.map +1 -1
  57. package/dist/source/sanitize-type-identifier.d.ts +3 -0
  58. package/dist/source/sanitize-type-identifier.d.ts.map +1 -0
  59. package/dist/source/sanitize-type-identifier.js +20 -0
  60. package/dist/source/sanitize-type-identifier.js.map +1 -0
  61. package/package.json +11 -1
  62. package/src/class/any-class.ts +2 -0
  63. package/src/index.ts +0 -1
  64. package/src/log/index.ts +1 -1
  65. package/src/log/logger.ts +1 -1
  66. package/src/map/get-or-insert.ts +1 -1
  67. package/src/predicate/index.ts +0 -4
  68. package/src/process/index.ts +2 -1
  69. package/src/process/install-graceful-shutdown.ts +1 -1
  70. package/src/process/kill-marked-processes.ts +44 -0
  71. package/src/process/process-guard.ts +20 -0
  72. package/src/process/resolve-executable.ts +9 -5
  73. package/src/process/spawn-with-parent-death-signal.ts +74 -0
  74. package/src/source/escape-reserved.ts +16 -0
  75. package/src/source/index.ts +1 -0
  76. package/src/source/sanitize-identifier.ts +5 -2
  77. package/src/source/sanitize-type-identifier.ts +22 -0
  78. package/dist/predicate/is-same-array-by.d.ts +0 -3
  79. package/dist/predicate/is-same-array-by.d.ts.map +0 -1
  80. package/dist/predicate/is-same-array-by.js +0 -8
  81. package/dist/predicate/is-same-array-by.js.map +0 -1
  82. package/dist/predicate/is-same-array.d.ts +0 -3
  83. package/dist/predicate/is-same-array.d.ts.map +0 -1
  84. package/dist/predicate/is-same-array.js +0 -6
  85. package/dist/predicate/is-same-array.js.map +0 -1
  86. package/dist/predicate/is-shallow-equal.d.ts +0 -3
  87. package/dist/predicate/is-shallow-equal.d.ts.map +0 -1
  88. package/dist/predicate/is-shallow-equal.js +0 -14
  89. package/dist/predicate/is-shallow-equal.js.map +0 -1
  90. package/dist/util/index.d.ts +0 -2
  91. package/dist/util/index.d.ts.map +0 -1
  92. package/dist/util/index.js +0 -2
  93. package/dist/util/index.js.map +0 -1
  94. package/dist/util/package-version.d.ts +0 -3
  95. package/dist/util/package-version.d.ts.map +0 -1
  96. package/dist/util/package-version.js +0 -6
  97. package/dist/util/package-version.js.map +0 -1
  98. package/src/predicate/is-same-array-by.ts +0 -9
  99. package/src/predicate/is-same-array.ts +0 -7
  100. package/src/predicate/is-shallow-equal.ts +0 -18
  101. package/src/util/index.ts +0 -1
  102. package/src/util/package-version.ts +0 -7
@@ -1,3 +1,4 @@
1
+ import { escapeReserved } from "./escape-reserved.js";
1
2
  const RESERVED = new Set([
2
3
  "arguments",
3
4
  "await",
@@ -21,6 +22,7 @@ const RESERVED = new Set([
21
22
  "for",
22
23
  "function",
23
24
  "if",
25
+ "implements",
24
26
  "import",
25
27
  "in",
26
28
  "instanceof",
@@ -48,7 +50,7 @@ const RESERVED = new Set([
48
50
  "yield",
49
51
  ]);
50
52
  function sanitizeIdentifier(name) {
51
- return RESERVED.has(name) ? `${name}_` : name;
53
+ return escapeReserved(name, RESERVED);
52
54
  }
53
- export { sanitizeIdentifier };
55
+ export { RESERVED, sanitizeIdentifier };
54
56
  //# sourceMappingURL=sanitize-identifier.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize-identifier.js","sourceRoot":"","sources":["../../src/source/sanitize-identifier.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAgB,IAAI,GAAG,CAAC;IAClC,WAAW;IACX,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,UAAU;IACV,UAAU;IACV,SAAS;IACT,QAAQ;IACR,IAAI;IACJ,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,SAAS;IACT,OAAO;IACP,SAAS;IACT,KAAK;IACL,UAAU;IACV,IAAI;IACJ,QAAQ;IACR,IAAI;IACJ,YAAY;IACZ,WAAW;IACX,KAAK;IACL,KAAK;IACL,MAAM;IACN,SAAS;IACT,SAAS;IACT,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,QAAQ;IACR,KAAK;IACL,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;CACV,CAAC,CAAC;AAEH,SAAS,kBAAkB,CAAC,IAAY;IACpC,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC","sourcesContent":["const RESERVED: Set<string> = new Set([\n \"arguments\",\n \"await\",\n \"break\",\n \"case\",\n \"catch\",\n \"class\",\n \"const\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"enum\",\n \"eval\",\n \"export\",\n \"extends\",\n \"false\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"import\",\n \"in\",\n \"instanceof\",\n \"interface\",\n \"let\",\n \"new\",\n \"null\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"return\",\n \"static\",\n \"super\",\n \"switch\",\n \"this\",\n \"throw\",\n \"true\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\",\n \"yield\",\n]);\n\nfunction sanitizeIdentifier(name: string): string {\n return RESERVED.has(name) ? `${name}_` : name;\n}\n\nexport { sanitizeIdentifier };\n"]}
1
+ {"version":3,"file":"sanitize-identifier.js","sourceRoot":"","sources":["../../src/source/sanitize-identifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,QAAQ,GAAgB,IAAI,GAAG,CAAC;IAClC,WAAW;IACX,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,UAAU;IACV,UAAU;IACV,SAAS;IACT,QAAQ;IACR,IAAI;IACJ,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,SAAS;IACT,OAAO;IACP,SAAS;IACT,KAAK;IACL,UAAU;IACV,IAAI;IACJ,YAAY;IACZ,QAAQ;IACR,IAAI;IACJ,YAAY;IACZ,WAAW;IACX,KAAK;IACL,KAAK;IACL,MAAM;IACN,SAAS;IACT,SAAS;IACT,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,QAAQ;IACR,KAAK;IACL,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;CACV,CAAC,CAAC;AAEH,SAAS,kBAAkB,CAAC,IAAY;IACpC,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC","sourcesContent":["import { escapeReserved } from \"./escape-reserved.ts\";\n\nconst RESERVED: Set<string> = new Set([\n \"arguments\",\n \"await\",\n \"break\",\n \"case\",\n \"catch\",\n \"class\",\n \"const\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"enum\",\n \"eval\",\n \"export\",\n \"extends\",\n \"false\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"implements\",\n \"import\",\n \"in\",\n \"instanceof\",\n \"interface\",\n \"let\",\n \"new\",\n \"null\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"return\",\n \"static\",\n \"super\",\n \"switch\",\n \"this\",\n \"throw\",\n \"true\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\",\n \"yield\",\n]);\n\nfunction sanitizeIdentifier(name: string): string {\n return escapeReserved(name, RESERVED);\n}\n\nexport { RESERVED, sanitizeIdentifier };\n"]}
@@ -0,0 +1,3 @@
1
+ declare function sanitizeTypeIdentifier(name: string): string;
2
+ export { sanitizeTypeIdentifier };
3
+ //# sourceMappingURL=sanitize-type-identifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-type-identifier.d.ts","sourceRoot":"","sources":["../../src/source/sanitize-type-identifier.ts"],"names":[],"mappings":"AAiBA,iBAAS,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { escapeReserved } from "./escape-reserved.js";
2
+ import { RESERVED } from "./sanitize-identifier.js";
3
+ const TYPE_RESERVED = new Set([
4
+ ...RESERVED,
5
+ "any",
6
+ "bigint",
7
+ "boolean",
8
+ "never",
9
+ "number",
10
+ "object",
11
+ "string",
12
+ "symbol",
13
+ "undefined",
14
+ "unknown",
15
+ ]);
16
+ function sanitizeTypeIdentifier(name) {
17
+ return escapeReserved(name, TYPE_RESERVED);
18
+ }
19
+ export { sanitizeTypeIdentifier };
20
+ //# sourceMappingURL=sanitize-type-identifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-type-identifier.js","sourceRoot":"","sources":["../../src/source/sanitize-type-identifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,MAAM,aAAa,GAAgB,IAAI,GAAG,CAAC;IACvC,GAAG,QAAQ;IACX,KAAK;IACL,QAAQ;IACR,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,WAAW;IACX,SAAS;CACZ,CAAC,CAAC;AAEH,SAAS,sBAAsB,CAAC,IAAY;IACxC,OAAO,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC","sourcesContent":["import { escapeReserved } from \"./escape-reserved.ts\";\nimport { RESERVED } from \"./sanitize-identifier.ts\";\n\nconst TYPE_RESERVED: Set<string> = new Set([\n ...RESERVED,\n \"any\",\n \"bigint\",\n \"boolean\",\n \"never\",\n \"number\",\n \"object\",\n \"string\",\n \"symbol\",\n \"undefined\",\n \"unknown\",\n]);\n\nfunction sanitizeTypeIdentifier(name: string): string {\n return escapeReserved(name, TYPE_RESERVED);\n}\n\nexport { sanitizeTypeIdentifier };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/utils",
3
- "version": "1.0.0-rc.4",
3
+ "version": "1.1.0",
4
4
  "description": "Cross-package utilities shared by the GTKX packages and toolchain: logging, error formatting, string and class helpers",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -34,6 +34,16 @@
34
34
  "dist",
35
35
  "src"
36
36
  ],
37
+ "nx": {
38
+ "targets": {
39
+ "lint": {
40
+ "options": {
41
+ "cwd": ".",
42
+ "command": "eslint {projectRoot}"
43
+ }
44
+ }
45
+ }
46
+ },
37
47
  "dependencies": {
38
48
  "picocolors": "^1.1.1"
39
49
  },
@@ -1,6 +1,8 @@
1
+ /** Any class constructor, abstract ones included, whose instances are `T`. */
1
2
  type AnyClass<T extends object = object> = (abstract new (
2
3
  ...args: never[]
3
4
  ) => T) & {
5
+ /** Object the class's instances inherit from. */
4
6
  prototype: T;
5
7
  };
6
8
 
package/src/index.ts CHANGED
@@ -9,4 +9,3 @@ export * from "./process/index.ts";
9
9
  export * from "./set/index.ts";
10
10
  export * from "./source/index.ts";
11
11
  export * from "./string/index.ts";
12
- export * from "./util/index.ts";
package/src/log/index.ts CHANGED
@@ -2,4 +2,4 @@ export { createLogger } from "./create-logger.ts";
2
2
  export { error, info, logger, warn } from "./default-logger.ts";
3
3
  /** @internal */
4
4
  export { debug } from "./default-logger.ts";
5
- export { Logger, type OutputStream } from "./logger.ts";
5
+ export { Logger } from "./logger.ts";
package/src/log/logger.ts CHANGED
@@ -98,4 +98,4 @@ class Logger {
98
98
  }
99
99
  }
100
100
 
101
- export { Logger, type OutputStream, type LoggerOptions };
101
+ export { Logger, type LoggerOptions };
@@ -15,4 +15,4 @@ function getOrInsert<K, V>(map: GetSet<K, V>, key: K, factory: (key: K) => V): V
15
15
  return value;
16
16
  }
17
17
 
18
- export { getOrInsert, type GetSet };
18
+ export { getOrInsert };
@@ -1,6 +1,2 @@
1
1
  export { isDeepEqual } from "./is-deep-equal.ts";
2
- export { isPlainObject } from "./is-plain-object.ts";
3
2
  export { isRecord } from "./is-record.ts";
4
- export { isSameArrayBy } from "./is-same-array-by.ts";
5
- export { isSameArray } from "./is-same-array.ts";
6
- export { isShallowEqual } from "./is-shallow-equal.ts";
@@ -1,3 +1,4 @@
1
1
  export { exitCodeForSignal } from "./exit-code-for-signal.ts";
2
2
  export { installGracefulShutdown } from "./install-graceful-shutdown.ts";
3
- export { resolveExecutable } from "./resolve-executable.ts";
3
+ export { resolveExecutable, tryResolveExecutable } from "./resolve-executable.ts";
4
+ export { spawnWithParentDeathSignal } from "./spawn-with-parent-death-signal.ts";
@@ -117,4 +117,4 @@ function installGracefulShutdown(options: GracefulShutdownOptions): void {
117
117
  }
118
118
  }
119
119
 
120
- export { installGracefulShutdown, type GracefulShutdownOptions };
120
+ export { installGracefulShutdown };
@@ -0,0 +1,44 @@
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+
3
+ const PROCESS_MARKER = "GTKX_PROCESS_GUARD";
4
+ const MAX_KILL_PASSES = 8;
5
+
6
+ const isMarked = (pid: number, prefix: string): boolean => {
7
+ try {
8
+ return readFileSync(`/proc/${String(pid)}/environ`, "utf8")
9
+ .split("\0")
10
+ .some((assignment) => assignment.startsWith(prefix));
11
+ } catch {
12
+ return false;
13
+ }
14
+ };
15
+
16
+ const markedPids = (prefix: string): number[] =>
17
+ readdirSync("/proc")
18
+ .map(Number)
19
+ .filter((pid) => Number.isSafeInteger(pid) && pid > 1 && pid !== process.pid)
20
+ .filter((pid) => isMarked(pid, prefix));
21
+
22
+ const killPid = (pid: number): void => {
23
+ try {
24
+ process.kill(pid, "SIGKILL");
25
+ } catch {
26
+ return;
27
+ }
28
+ };
29
+
30
+ function killMarkedProcesses(prefix: string): void {
31
+ for (let pass = 0; pass < MAX_KILL_PASSES; pass += 1) {
32
+ const pids = markedPids(prefix);
33
+
34
+ if (pids.length === 0) {
35
+ return;
36
+ }
37
+
38
+ for (const pid of pids) {
39
+ killPid(pid);
40
+ }
41
+ }
42
+ }
43
+
44
+ export { PROCESS_MARKER, killMarkedProcesses };
@@ -0,0 +1,20 @@
1
+ import { killMarkedProcesses } from "./kill-marked-processes.ts";
2
+
3
+ const GUARD_PREFIX = process.argv[2] ?? "";
4
+ const WATCHED_SIGNALS = ["SIGTERM", "SIGINT", "SIGHUP"] as const satisfies NodeJS.Signals[];
5
+
6
+ const sweep = (): void => {
7
+ if (GUARD_PREFIX.length > 0) {
8
+ killMarkedProcesses(GUARD_PREFIX);
9
+ }
10
+
11
+ process.exit(0);
12
+ };
13
+
14
+ process.stdin.resume();
15
+ process.stdin.on("end", sweep);
16
+ process.stdin.on("error", sweep);
17
+
18
+ for (const signal of WATCHED_SIGNALS) {
19
+ process.on(signal, sweep);
20
+ }
@@ -1,11 +1,11 @@
1
- import { accessSync, constants } from "node:fs";
1
+ import { accessSync, constants, statSync } from "node:fs";
2
2
  import { delimiter, isAbsolute, join, resolve } from "node:path";
3
3
 
4
4
  const isExecutable = (path: string): boolean => {
5
5
  try {
6
6
  accessSync(path, constants.X_OK);
7
7
 
8
- return true;
8
+ return statSync(path).isFile();
9
9
  } catch {
10
10
  return false;
11
11
  }
@@ -25,7 +25,7 @@ const findOnPath = (command: string): string | undefined => {
25
25
  return undefined;
26
26
  };
27
27
 
28
- function resolveExecutable(command: string): string {
28
+ function tryResolveExecutable(command: string): string | undefined {
29
29
  if (isAbsolute(command)) {
30
30
  return command;
31
31
  }
@@ -34,7 +34,11 @@ function resolveExecutable(command: string): string {
34
34
  return resolve(command);
35
35
  }
36
36
 
37
- const found = findOnPath(command);
37
+ return findOnPath(command);
38
+ }
39
+
40
+ function resolveExecutable(command: string): string {
41
+ const found = tryResolveExecutable(command);
38
42
 
39
43
  if (found === undefined) {
40
44
  throw new Error(`Cannot find the "${command}" executable on PATH`);
@@ -43,4 +47,4 @@ function resolveExecutable(command: string): string {
43
47
  return found;
44
48
  }
45
49
 
46
- export { resolveExecutable };
50
+ export { resolveExecutable, tryResolveExecutable };
@@ -0,0 +1,74 @@
1
+ import { type ChildProcess, spawn, type StdioOptions } from "node:child_process";
2
+ import { randomBytes } from "node:crypto";
3
+ import { Socket } from "node:net";
4
+ import { dirname, extname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { killMarkedProcesses, PROCESS_MARKER } from "./kill-marked-processes.ts";
7
+ import { resolveExecutable } from "./resolve-executable.ts";
8
+
9
+ type ParentDeathSpawnOptions = {
10
+ stdio?: StdioOptions;
11
+ env?: NodeJS.ProcessEnv;
12
+ };
13
+
14
+ type GuardState = {
15
+ child?: ChildProcess | undefined;
16
+ };
17
+
18
+ const MODULE_PATH = fileURLToPath(import.meta.url);
19
+ const GUARD_PATH = join(dirname(MODULE_PATH), `process-guard${extname(MODULE_PATH)}`);
20
+ const RUN_ID = randomBytes(8).toString("hex");
21
+ const RUN_PREFIX = `${PROCESS_MARKER}=${RUN_ID}/`;
22
+ const guard: GuardState = {};
23
+
24
+ const releaseGuard = (child: ChildProcess): void => {
25
+ child.unref();
26
+ const { stdin } = child;
27
+
28
+ if (stdin instanceof Socket) {
29
+ stdin.unref();
30
+ }
31
+ };
32
+
33
+ const startGuard = (): void => {
34
+ if (guard.child) {
35
+ return;
36
+ }
37
+
38
+ const child = spawn(process.execPath, [GUARD_PATH, RUN_PREFIX], {
39
+ detached: true,
40
+ stdio: ["pipe", "ignore", "ignore"],
41
+ });
42
+
43
+ child.on("error", () => {
44
+ guard.child = undefined;
45
+ });
46
+
47
+ guard.child = child;
48
+ releaseGuard(child);
49
+ };
50
+
51
+ function spawnWithParentDeathSignal(
52
+ command: string,
53
+ args: string[],
54
+ options: ParentDeathSpawnOptions = {},
55
+ ): ChildProcess {
56
+ const executable = resolveExecutable(command);
57
+ const setpriv = resolveExecutable("setpriv");
58
+ const jobValue = `${RUN_ID}/${randomBytes(4).toString("hex")}`;
59
+ startGuard();
60
+
61
+ const child = spawn(setpriv, ["--pdeathsig", "SIGKILL", executable, ...args], {
62
+ detached: true,
63
+ stdio: options.stdio ?? "ignore",
64
+ env: { ...(options.env ?? process.env), [PROCESS_MARKER]: jobValue },
65
+ });
66
+
67
+ child.on("exit", () => {
68
+ killMarkedProcesses(`${PROCESS_MARKER}=${jobValue}`);
69
+ });
70
+
71
+ return child;
72
+ }
73
+
74
+ export { spawnWithParentDeathSignal };
@@ -0,0 +1,16 @@
1
+ const UNDERSCORE = "_";
2
+
3
+ const getUnsuffixedName = (name: string): string => {
4
+ let end = name.length;
5
+
6
+ while (end > 0 && name.charAt(end - 1) === UNDERSCORE) {
7
+ end -= 1;
8
+ }
9
+
10
+ return name.slice(0, end);
11
+ };
12
+
13
+ const escapeReserved = (name: string, reserved: Set<string>): string =>
14
+ reserved.has(getUnsuffixedName(name)) ? `${name}${UNDERSCORE}` : name;
15
+
16
+ export { escapeReserved };
@@ -1,3 +1,4 @@
1
1
  export { sanitizeIdentifier } from "./sanitize-identifier.ts";
2
+ export { sanitizeTypeIdentifier } from "./sanitize-type-identifier.ts";
2
3
  export { sourceStringLiteral } from "./source-string-literal.ts";
3
4
  export { toCamelIdentifier } from "./to-camel-identifier.ts";
@@ -1,3 +1,5 @@
1
+ import { escapeReserved } from "./escape-reserved.ts";
2
+
1
3
  const RESERVED: Set<string> = new Set([
2
4
  "arguments",
3
5
  "await",
@@ -21,6 +23,7 @@ const RESERVED: Set<string> = new Set([
21
23
  "for",
22
24
  "function",
23
25
  "if",
26
+ "implements",
24
27
  "import",
25
28
  "in",
26
29
  "instanceof",
@@ -49,7 +52,7 @@ const RESERVED: Set<string> = new Set([
49
52
  ]);
50
53
 
51
54
  function sanitizeIdentifier(name: string): string {
52
- return RESERVED.has(name) ? `${name}_` : name;
55
+ return escapeReserved(name, RESERVED);
53
56
  }
54
57
 
55
- export { sanitizeIdentifier };
58
+ export { RESERVED, sanitizeIdentifier };
@@ -0,0 +1,22 @@
1
+ import { escapeReserved } from "./escape-reserved.ts";
2
+ import { RESERVED } from "./sanitize-identifier.ts";
3
+
4
+ const TYPE_RESERVED: Set<string> = new Set([
5
+ ...RESERVED,
6
+ "any",
7
+ "bigint",
8
+ "boolean",
9
+ "never",
10
+ "number",
11
+ "object",
12
+ "string",
13
+ "symbol",
14
+ "undefined",
15
+ "unknown",
16
+ ]);
17
+
18
+ function sanitizeTypeIdentifier(name: string): string {
19
+ return escapeReserved(name, TYPE_RESERVED);
20
+ }
21
+
22
+ export { sanitizeTypeIdentifier };
@@ -1,3 +0,0 @@
1
- declare function isSameArrayBy<T>(a: T[], b: T[], isEqual: (x: T, y: T) => boolean): boolean;
2
- export { isSameArrayBy };
3
- //# sourceMappingURL=is-same-array-by.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-same-array-by.d.ts","sourceRoot":"","sources":["../../src/predicate/is-same-array-by.ts"],"names":[],"mappings":"AAAA,iBAAS,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAMnF;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -1,8 +0,0 @@
1
- function isSameArrayBy(a, b, isEqual) {
2
- if (a.length !== b.length) {
3
- return false;
4
- }
5
- return a.every((item, index) => isEqual(item, b[index]));
6
- }
7
- export { isSameArrayBy };
8
- //# sourceMappingURL=is-same-array-by.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-same-array-by.js","sourceRoot":"","sources":["../../src/predicate/is-same-array-by.ts"],"names":[],"mappings":"AAAA,SAAS,aAAa,CAAI,CAAM,EAAE,CAAM,EAAE,OAAgC;IACtE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAM,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC","sourcesContent":["function isSameArrayBy<T>(a: T[], b: T[], isEqual: (x: T, y: T) => boolean): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n return a.every((item, index) => isEqual(item, b[index] as T));\n}\n\nexport { isSameArrayBy };\n"]}
@@ -1,3 +0,0 @@
1
- declare function isSameArray<T>(a: T[], b: T[]): boolean;
2
- export { isSameArray };
3
- //# sourceMappingURL=is-same-array.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-same-array.d.ts","sourceRoot":"","sources":["../../src/predicate/is-same-array.ts"],"names":[],"mappings":"AAEA,iBAAS,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,OAAO,CAE/C;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -1,6 +0,0 @@
1
- import { isSameArrayBy } from "./is-same-array-by.js";
2
- function isSameArray(a, b) {
3
- return isSameArrayBy(a, b, (x, y) => x === y);
4
- }
5
- export { isSameArray };
6
- //# sourceMappingURL=is-same-array.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-same-array.js","sourceRoot":"","sources":["../../src/predicate/is-same-array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,SAAS,WAAW,CAAI,CAAM,EAAE,CAAM;IAClC,OAAO,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,CAAC","sourcesContent":["import { isSameArrayBy } from \"./is-same-array-by.ts\";\n\nfunction isSameArray<T>(a: T[], b: T[]): boolean {\n return isSameArrayBy(a, b, (x, y) => x === y);\n}\n\nexport { isSameArray };\n"]}
@@ -1,3 +0,0 @@
1
- declare function isShallowEqual(a: unknown, b: unknown): boolean;
2
- export { isShallowEqual };
3
- //# sourceMappingURL=is-shallow-equal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-shallow-equal.d.ts","sourceRoot":"","sources":["../../src/predicate/is-shallow-equal.ts"],"names":[],"mappings":"AAKA,iBAAS,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAUvD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -1,14 +0,0 @@
1
- import { areObjectKeysEqual } from "./are-object-keys-equal.js";
2
- import { isPlainObject } from "./is-plain-object.js";
3
- const isStrictEqual = (a, b) => a === b;
4
- function isShallowEqual(a, b) {
5
- if (a === b) {
6
- return true;
7
- }
8
- if (isPlainObject(a) && isPlainObject(b)) {
9
- return areObjectKeysEqual(a, b, isStrictEqual);
10
- }
11
- return false;
12
- }
13
- export { isShallowEqual };
14
- //# sourceMappingURL=is-shallow-equal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-shallow-equal.js","sourceRoot":"","sources":["../../src/predicate/is-shallow-equal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,aAAa,GAAG,CAAC,CAAU,EAAE,CAAU,EAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;AAEnE,SAAS,cAAc,CAAC,CAAU,EAAE,CAAU;IAC1C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,aAAa,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC","sourcesContent":["import { areObjectKeysEqual } from \"./are-object-keys-equal.ts\";\nimport { isPlainObject } from \"./is-plain-object.ts\";\n\nconst isStrictEqual = (a: unknown, b: unknown): boolean => a === b;\n\nfunction isShallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) {\n return true;\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n return areObjectKeysEqual(a, b, isStrictEqual);\n }\n\n return false;\n}\n\nexport { isShallowEqual };\n"]}
@@ -1,2 +0,0 @@
1
- export { packageVersion } from "./package-version.ts";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,2 +0,0 @@
1
- export { packageVersion } from "./package-version.js";
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["export { packageVersion } from \"./package-version.ts\";\n"]}
@@ -1,3 +0,0 @@
1
- declare function packageVersion(importMetaUrl: string): string;
2
- export { packageVersion };
3
- //# sourceMappingURL=package-version.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../../src/util/package-version.ts"],"names":[],"mappings":"AAEA,iBAAS,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -1,6 +0,0 @@
1
- import { createRequire } from "node:module";
2
- function packageVersion(importMetaUrl) {
3
- return createRequire(importMetaUrl)("../package.json").version;
4
- }
5
- export { packageVersion };
6
- //# sourceMappingURL=package-version.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"package-version.js","sourceRoot":"","sources":["../../src/util/package-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,cAAc,CAAC,aAAqB;IACzC,OAAQ,aAAa,CAAC,aAAa,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC;AAC5F,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC","sourcesContent":["import { createRequire } from \"node:module\";\n\nfunction packageVersion(importMetaUrl: string): string {\n return (createRequire(importMetaUrl)(\"../package.json\") as { version: string }).version;\n}\n\nexport { packageVersion };\n"]}
@@ -1,9 +0,0 @@
1
- function isSameArrayBy<T>(a: T[], b: T[], isEqual: (x: T, y: T) => boolean): boolean {
2
- if (a.length !== b.length) {
3
- return false;
4
- }
5
-
6
- return a.every((item, index) => isEqual(item, b[index] as T));
7
- }
8
-
9
- export { isSameArrayBy };
@@ -1,7 +0,0 @@
1
- import { isSameArrayBy } from "./is-same-array-by.ts";
2
-
3
- function isSameArray<T>(a: T[], b: T[]): boolean {
4
- return isSameArrayBy(a, b, (x, y) => x === y);
5
- }
6
-
7
- export { isSameArray };
@@ -1,18 +0,0 @@
1
- import { areObjectKeysEqual } from "./are-object-keys-equal.ts";
2
- import { isPlainObject } from "./is-plain-object.ts";
3
-
4
- const isStrictEqual = (a: unknown, b: unknown): boolean => a === b;
5
-
6
- function isShallowEqual(a: unknown, b: unknown): boolean {
7
- if (a === b) {
8
- return true;
9
- }
10
-
11
- if (isPlainObject(a) && isPlainObject(b)) {
12
- return areObjectKeysEqual(a, b, isStrictEqual);
13
- }
14
-
15
- return false;
16
- }
17
-
18
- export { isShallowEqual };
package/src/util/index.ts DELETED
@@ -1 +0,0 @@
1
- export { packageVersion } from "./package-version.ts";
@@ -1,7 +0,0 @@
1
- import { createRequire } from "node:module";
2
-
3
- function packageVersion(importMetaUrl: string): string {
4
- return (createRequire(importMetaUrl)("../package.json") as { version: string }).version;
5
- }
6
-
7
- export { packageVersion };