@gtkx/utils 0.21.0 → 1.0.0-rc.1

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 (52) hide show
  1. package/README.md +173 -0
  2. package/dist/class.d.ts +17 -11
  3. package/dist/class.d.ts.map +1 -1
  4. package/dist/class.js +27 -1
  5. package/dist/class.js.map +1 -1
  6. package/dist/collection.d.ts +17 -45
  7. package/dist/collection.d.ts.map +1 -1
  8. package/dist/collection.js +42 -76
  9. package/dist/collection.js.map +1 -1
  10. package/dist/error.d.ts +16 -8
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/error.js +35 -8
  13. package/dist/error.js.map +1 -1
  14. package/dist/graceful-shutdown.d.ts +9 -57
  15. package/dist/graceful-shutdown.d.ts.map +1 -1
  16. package/dist/graceful-shutdown.js +70 -75
  17. package/dist/graceful-shutdown.js.map +1 -1
  18. package/dist/index.d.ts +9 -6
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +9 -5
  21. package/dist/index.js.map +1 -1
  22. package/dist/log.d.ts +103 -0
  23. package/dist/log.d.ts.map +1 -0
  24. package/dist/log.js +129 -0
  25. package/dist/log.js.map +1 -0
  26. package/dist/package-version.d.ts +7 -0
  27. package/dist/package-version.d.ts.map +1 -0
  28. package/dist/package-version.js +8 -0
  29. package/dist/package-version.js.map +1 -0
  30. package/dist/reflect.d.ts +11 -0
  31. package/dist/reflect.d.ts.map +1 -0
  32. package/dist/reflect.js +14 -0
  33. package/dist/reflect.js.map +1 -0
  34. package/dist/source.d.ts +12 -25
  35. package/dist/source.d.ts.map +1 -1
  36. package/dist/source.js +20 -41
  37. package/dist/source.js.map +1 -1
  38. package/dist/string.d.ts +13 -40
  39. package/dist/string.d.ts.map +1 -1
  40. package/dist/string.js +18 -48
  41. package/dist/string.js.map +1 -1
  42. package/package.json +20 -7
  43. package/src/class.ts +30 -11
  44. package/src/collection.ts +43 -81
  45. package/src/error.ts +38 -8
  46. package/src/graceful-shutdown.ts +87 -114
  47. package/src/index.ts +18 -9
  48. package/src/log.ts +164 -0
  49. package/src/package-version.ts +9 -0
  50. package/src/reflect.ts +13 -0
  51. package/src/source.ts +24 -43
  52. package/src/string.ts +19 -47
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/logo.svg" alt="GTKX" width="100" />
3
+ </p>
4
+
5
+ <h1 align="center">GTKX</h1>
6
+
7
+ <p align="center">
8
+ The React framework for Linux.<br />
9
+ Build GTK4 and Adwaita apps in TypeScript, with React components and hooks driving GNOME's own widgets. What you ship is a GNOME app.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/v/create-gtkx?color=cb3837&logo=npm&label=create-gtkx" alt="npm version" /></a>
14
+ <a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/dm/create-gtkx?color=cb3837&logo=npm&label=downloads" alt="npm downloads" /></a>
15
+ <img src="https://img.shields.io/badge/node-%E2%89%A524-339933?logo=node.js&logoColor=white" alt="Node >= 24" />
16
+ <a href="https://github.com/gtkx-org/gtkx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MPL--2.0-blue.svg" alt="License: MPL-2.0" /></a>
17
+ <a href="https://github.com/gtkx-org/gtkx/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/gtkx-org/gtkx/ci.yml?branch=main&logo=github&label=CI" alt="CI status" /></a>
18
+ <img src="https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white" alt="TypeScript" />
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a href="https://gtkx.dev">Homepage</a> &middot;
23
+ <a href="https://gtkx.dev/guide/why-gtkx">Documentation</a> &middot;
24
+ <a href="https://github.com/gtkx-org/gtkx/tree/main/examples">Examples</a> &middot;
25
+ <a href="https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md">Contributing</a>
26
+ </p>
27
+
28
+ ---
29
+
30
+ GTKX generates fully typed bindings for the entire GTK4 and Adwaita surface directly from GObject-Introspection. On top of those bindings you get the React programming model: components and hooks driving GObject instances, with Fast Refresh while you develop.
31
+
32
+ <p align="center">
33
+ <img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/examples/tutorial/assets/screenshot.png" alt="The Tasks app: an Adwaita window with a sidebar of smart views and colored lists on the left, and a boxed task list on the right." />
34
+ </p>
35
+
36
+ <p align="center">
37
+ <em>The Tasks app you build in the <a href="https://gtkx.dev/tutorial/">tutorial</a>.</em>
38
+ </p>
39
+
40
+ ## Demo
41
+
42
+ The intrinsic elements in this snippet render GTK4 widgets, and ordinary React hooks and events drive them:
43
+
44
+ ```tsx
45
+ import * as Gtk from "@gtkx/gi/gtk";
46
+ import { GtkApplication, GtkApplicationWindow, GtkBox, GtkButton, GtkLabel } from "@gtkx/jsx/gtk";
47
+ import { createRoot, quit } from "@gtkx/react";
48
+ import { useState } from "react";
49
+
50
+ const Counter = () => {
51
+ const [count, setCount] = useState(0);
52
+
53
+ return (
54
+ <GtkApplicationWindow
55
+ title="Hello GTKX"
56
+ defaultWidth={400}
57
+ defaultHeight={300}
58
+ onCloseRequest={quit}
59
+ >
60
+ <GtkBox
61
+ orientation={Gtk.Orientation.VERTICAL}
62
+ spacing={20}
63
+ marginTop={40}
64
+ marginBottom={40}
65
+ marginStart={40}
66
+ marginEnd={40}
67
+ valign={Gtk.Align.CENTER}
68
+ halign={Gtk.Align.CENTER}
69
+ >
70
+ <GtkLabel cssClasses={["title-1"]}>Welcome to GTKX!</GtkLabel>
71
+ <GtkLabel cssClasses={["title-2"]}>{`Count: ${count}`}</GtkLabel>
72
+ <GtkButton
73
+ label="Increment"
74
+ onClicked={() => setCount((c) => c + 1)}
75
+ cssClasses={["suggested-action", "pill"]}
76
+ />
77
+ </GtkBox>
78
+ </GtkApplicationWindow>
79
+ );
80
+ };
81
+
82
+ const App = () => (
83
+ <GtkApplication>
84
+ <Counter />
85
+ </GtkApplication>
86
+ );
87
+
88
+ createRoot().render(<App />);
89
+ ```
90
+
91
+ This is the [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world) example, with `app.tsx` and `index.tsx` combined into a single snippet. `@gtkx/gi` and `@gtkx/jsx` are per-project bindings generated by the CLI, not packages you install from npm.
92
+
93
+ ## Why GTKX
94
+
95
+ ### A declarative layer for the GNOME stack
96
+
97
+ GTK4 is mature, and GtkBuilder XML can lay out a static interface, but nothing re-renders that interface when your application state changes, and nothing hot-reloads it as you work. GTKX adds that missing layer, and the tooling around it, on top of the stack you already know:
98
+
99
+ - a React reconciler that exposes every GObject as a JSX element,
100
+ - a CLI for scaffolding, development, and production builds,
101
+ - a dev server with Fast Refresh that patches your running UI in place,
102
+ - CSS-in-JS styling and high-level list, grid, and dialog components,
103
+ - a Testing Library-style API for querying and driving your widgets in tests,
104
+ - and a Model Context Protocol (MCP) server that exposes your live app to AI agents.
105
+
106
+ ### The full GNOME API surface
107
+
108
+ React Native and similar frameworks hide the native toolkit so one API can run everywhere. GTKX exposes it: GTK4, Adwaita, and any other GObject-Introspection library on your system. Linux-only by design.
109
+
110
+ ### Why Node.js, and why generated bindings
111
+
112
+ GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [why-gtkx guide](https://gtkx.dev/guide/why-gtkx) covers the comparison in full.
113
+
114
+ GTKX generates the TypeScript types and the native FFI calls from the same GObject-Introspection data, so the types cannot drift from the calls they back. Codegen covers the whole GTK4 and Adwaita surface.
115
+
116
+ At runtime, the native Rust core calls straight into the system GTK4, Adwaita, and GLib libraries through libffi, without loading libgirepository at all.
117
+
118
+ ## Quick start
119
+
120
+ GTKX is Linux-only and needs Node.js 24 or later. See [Requirements](#requirements).
121
+
122
+ Scaffold a new app with the `create-gtkx` initializer:
123
+
124
+ ```sh
125
+ npm create gtkx@rc
126
+ ```
127
+
128
+ The same command works with other package managers: `pnpm create gtkx@rc` or `yarn create gtkx@rc`.
129
+
130
+ Then run your new app:
131
+
132
+ ```sh
133
+ cd my-app
134
+ npm run dev
135
+ ```
136
+
137
+ To go further, follow the [tutorial](https://gtkx.dev/tutorial/).
138
+
139
+ ## Documentation
140
+
141
+ The documentation at **[gtkx.dev](https://gtkx.dev)** includes a step-by-step tutorial that builds a complete GNOME app, from scaffolding to packaging and shipping, plus guides and a full API reference.
142
+
143
+ **[Read the docs &rarr;](https://gtkx.dev/guide/why-gtkx)**
144
+
145
+ ## Requirements
146
+
147
+ GTKX is Linux-only. You need:
148
+
149
+ - Linux with the GTK4 (4.20 or later), Adwaita (1.8 or later), and GLib development libraries
150
+ - Node.js 24 or later
151
+
152
+ The `@gtkx/native` addon ships prebuilt for x64 and arm64 glibc Linux; other targets need to build it from the GTKX repository, which requires a Rust toolchain.
153
+
154
+ ## Examples
155
+
156
+ Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
157
+
158
+ - [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world): the counter above.
159
+ - [`gtk-demo`](https://github.com/gtkx-org/gtkx/tree/main/examples/gtk-demo): a React port of the official GTK4 widget showcase, covering lists, dialogs, gestures, CSS, and OpenGL.
160
+ - [`browser`](https://github.com/gtkx-org/gtkx/tree/main/examples/browser): a WebKitWebView-based web browser.
161
+ - [`tutorial`](https://github.com/gtkx-org/gtkx/tree/main/examples/tutorial): the Tasks app the documentation builds.
162
+
163
+ ## Status
164
+
165
+ GTKX 1.0 is at the release candidate stage.
166
+
167
+ ## Contributing
168
+
169
+ Contributions are welcome. See [CONTRIBUTING.md](https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md), the [Code of Conduct](https://github.com/gtkx-org/gtkx/blob/main/CODE_OF_CONDUCT.md), and the [security policy](https://github.com/gtkx-org/gtkx/blob/main/SECURITY.md). Building the repo needs Node.js 24 or later, pnpm, and a Rust toolchain.
170
+
171
+ ## License
172
+
173
+ GTKX is licensed under [MPL-2.0](https://github.com/gtkx-org/gtkx/blob/main/LICENSE).
package/dist/class.d.ts CHANGED
@@ -1,16 +1,22 @@
1
1
  /**
2
- * Structural type matching any class abstract or concrete whose instances
3
- * have type `T`.
4
- *
5
- * A class value carries a construct signature plus a `prototype`, but a bare
6
- * construct signature types `prototype` as `any`. The `& { prototype: T }`
7
- * intersection recovers the precise instance type so callers can read
8
- * `cls.prototype` as `T`, and the `abstract new` form accepts both abstract and
9
- * concrete classes, making this the widest supertype of every class value. The
10
- * `never[]` constructor parameters admit any class while documenting that the
11
- * type is used as an identity token, not to construct instances.
2
+ * A constructor value of any (possibly abstract) class producing instances of `T`.
12
3
  */
13
4
  export type AnyClass<T extends object = object> = (abstract new (...args: never[]) => T) & {
14
- readonly prototype: T;
5
+ prototype: T;
15
6
  };
7
+ /**
8
+ * Returns the direct superclass of `cls`, or `null` when it has no class ancestor.
9
+ *
10
+ * @param cls The class whose prototype parent to inspect.
11
+ */
12
+ export declare function getParentClass(cls: AnyClass): AnyClass | null;
13
+ /**
14
+ * Walks the class chain from `cls` up through its ancestors, calling `visit` on each and
15
+ * returning the first result that is not `undefined`.
16
+ *
17
+ * @param cls The class to start from, or `null` to visit nothing.
18
+ * @param visit Called with each class in the chain; a defined return value stops the walk.
19
+ * @returns The first defined result from `visit`, or `undefined` if none was produced.
20
+ */
21
+ export declare function walkClassChain<T>(cls: AnyClass | null, visit: (ancestor: AnyClass) => T | undefined): T | undefined;
16
22
  //# sourceMappingURL=class.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"class.d.ts","sourceRoot":"","sources":["../src/class.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,MACvD,GAAG,IAAI,EAAE,KAAK,EAAE,KACf,CAAC,CAAC,GAAG;IACN,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;CACzB,CAAC"}
1
+ {"version":3,"file":"class.d.ts","sourceRoot":"","sources":["../src/class.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,MACvD,GAAG,IAAI,EAAE,KAAK,EAAE,KACf,CAAC,CAAC,GAAG;IACN,SAAS,EAAE,CAAC,CAAC;CAChB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAG7D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS,CAQnH"}
package/dist/class.js CHANGED
@@ -1,2 +1,28 @@
1
- export {};
1
+ /**
2
+ * Returns the direct superclass of `cls`, or `null` when it has no class ancestor.
3
+ *
4
+ * @param cls The class whose prototype parent to inspect.
5
+ */
6
+ export function getParentClass(cls) {
7
+ const parent = Object.getPrototypeOf(cls);
8
+ return typeof parent === "function" && parent !== Function.prototype ? parent : null;
9
+ }
10
+ /**
11
+ * Walks the class chain from `cls` up through its ancestors, calling `visit` on each and
12
+ * returning the first result that is not `undefined`.
13
+ *
14
+ * @param cls The class to start from, or `null` to visit nothing.
15
+ * @param visit Called with each class in the chain; a defined return value stops the walk.
16
+ * @returns The first defined result from `visit`, or `undefined` if none was produced.
17
+ */
18
+ export function walkClassChain(cls, visit) {
19
+ let current = cls;
20
+ while (current !== null) {
21
+ const result = visit(current);
22
+ if (result !== undefined)
23
+ return result;
24
+ current = getParentClass(current);
25
+ }
26
+ return undefined;
27
+ }
2
28
  //# sourceMappingURL=class.js.map
package/dist/class.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"class.js","sourceRoot":"","sources":["../src/class.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"class.js","sourceRoot":"","sources":["../src/class.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAAa;IACxC,MAAM,MAAM,GAAY,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,OAAO,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAE,MAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;AACvG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAI,GAAoB,EAAE,KAA4C;IAChG,IAAI,OAAO,GAAG,GAAG,CAAC;IAClB,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QACxC,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC","sourcesContent":["/**\n * A constructor value of any (possibly abstract) class producing instances of `T`.\n */\nexport type AnyClass<T extends object = object> = (abstract new (\n ...args: never[]\n) => T) & {\n prototype: T;\n};\n\n/**\n * Returns the direct superclass of `cls`, or `null` when it has no class ancestor.\n *\n * @param cls The class whose prototype parent to inspect.\n */\nexport function getParentClass(cls: AnyClass): AnyClass | null {\n const parent: unknown = Object.getPrototypeOf(cls);\n return typeof parent === \"function\" && parent !== Function.prototype ? (parent as AnyClass) : null;\n}\n\n/**\n * Walks the class chain from `cls` up through its ancestors, calling `visit` on each and\n * returning the first result that is not `undefined`.\n *\n * @param cls The class to start from, or `null` to visit nothing.\n * @param visit Called with each class in the chain; a defined return value stops the walk.\n * @returns The first defined result from `visit`, or `undefined` if none was produced.\n */\nexport function walkClassChain<T>(cls: AnyClass | null, visit: (ancestor: AnyClass) => T | undefined): T | undefined {\n let current = cls;\n while (current !== null) {\n const result = visit(current);\n if (result !== undefined) return result;\n current = getParentClass(current);\n }\n return undefined;\n}\n"]}
@@ -1,58 +1,30 @@
1
1
  /**
2
- * Pure, runtime-agnostic collection helpers shared across GTKX packages.
3
- */
4
- /**
5
- * Returns a shallow copy of `record` with the given `keys` removed.
6
- *
7
- * Keys absent from `record` are ignored, and `record` is not mutated. The
8
- * result is typed as the input shape because callers treat the excluded keys
9
- * as runtime-only concerns absent from the static type.
2
+ * Returns the items with duplicates removed, keeping the first item for each distinct key.
10
3
  *
11
- * @typeParam T - The record shape.
12
- * @param record - The source object.
13
- * @param keys - The keys to exclude from the copy.
14
- * @returns A new object holding every own enumerable key of `record` except
15
- * those listed in `keys`.
4
+ * @param items The items to deduplicate.
5
+ * @param key Computes the identity string used to detect duplicates.
16
6
  */
17
- export declare const omit: <T extends Record<string, unknown>>(record: T, keys: readonly string[]) => T;
7
+ export declare const uniqBy: <T>(items: T[], key: (item: T) => string) => T[];
8
+ export declare const isSameArray: <T>(a: T[], b: T[]) => boolean;
18
9
  /**
19
- * Compares two arrays of primitives for element-wise strict equality.
10
+ * Returns a new array of the given strings sorted with locale-aware comparison.
20
11
  *
21
- * Returns `true` when both arguments are the same reference (including both
22
- * being `null` or `undefined`), or when they have equal length and every
23
- * element is strictly equal (`===`) at the same index. A `null`/`undefined`
24
- * argument is equal only to another `null`/`undefined` argument.
25
- *
26
- * @typeParam T - The primitive element type.
27
- * @param a - The first array, or `null`/`undefined`.
28
- * @param b - The second array, or `null`/`undefined`.
29
- * @returns Whether the two arrays are shallowly equal.
12
+ * @param values The strings to sort.
30
13
  */
31
- export declare const isShallowEqual: <T extends string | number | boolean>(a: readonly T[] | null | undefined, b: readonly T[] | null | undefined) => boolean;
14
+ export declare const sortStrings: (values: Iterable<string>) => string[];
32
15
  /**
33
- * Compares two arrays of records by shallow per-element equality.
34
- *
35
- * Returns `true` when both arrays have equal length and, at every index, the
36
- * two records expose the same set of keys with strictly equal (`===`) values.
37
- * Values are compared one level deep only; nested objects are compared by
38
- * reference.
16
+ * Returns a new array of the given items sorted by a locale-aware comparison of their keys.
39
17
  *
40
- * @typeParam T - The record element type.
41
- * @param a - The first array of records.
42
- * @param b - The second array of records.
43
- * @returns Whether the two arrays are element-wise shallowly equal.
18
+ * @param items The items to sort.
19
+ * @param key Computes the string to sort each item by.
44
20
  */
45
- export declare const isShallowArrayEqual: <T extends Record<string, unknown>>(a: readonly T[], b: readonly T[]) => boolean;
21
+ export declare const sortStringsBy: <T>(items: Iterable<T>, key: (item: T) => string) => T[];
46
22
  /**
47
- * Builds a reverse lookup from a numeric enum's values to their member names.
48
- *
49
- * A TypeScript numeric enum's runtime object carries both name-to-value and
50
- * value-to-name entries; this keeps only the name-to-value direction and
51
- * inverts it, yielding a `Map` from each numeric value to the name that
52
- * declared it.
23
+ * Determines whether two records have the same keys and strictly equal values.
53
24
  *
54
- * @param enumObject - A numeric enum's runtime object.
55
- * @returns A map from each numeric enum value to its declared member name.
25
+ * @param a The first record, or `undefined`.
26
+ * @param b The second record, or `undefined`.
27
+ * @returns `true` when both are the same reference, or both are defined with identical own keys and values.
56
28
  */
57
- export declare const reverseNumericEnum: (enumObject: Record<string, string | number>) => Map<number, string>;
29
+ export declare const isShallowEqual: <T extends Record<string, unknown>>(a?: T, b?: T) => boolean;
58
30
  //# sourceMappingURL=collection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,KAAG,CAQ5F,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,OAAO,EAC9D,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,EAClC,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,KACnC,OAQF,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,EAAE,KAAG,OAkBzG,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAK9F,CAAC"}
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,KAAG,CAAC,EAUjE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,KAAG,OAM/C,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,WAAW,WAAY,QAAQ,CAAC,MAAM,CAAC,KAAG,MAAM,EAAsC,CAAC;AAEpG;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,KAAG,CAAC,EACpB,CAAC;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAG,OAahF,CAAC"}
@@ -1,98 +1,64 @@
1
1
  /**
2
- * Pure, runtime-agnostic collection helpers shared across GTKX packages.
3
- */
4
- /**
5
- * Returns a shallow copy of `record` with the given `keys` removed.
2
+ * Returns the items with duplicates removed, keeping the first item for each distinct key.
6
3
  *
7
- * Keys absent from `record` are ignored, and `record` is not mutated. The
8
- * result is typed as the input shape because callers treat the excluded keys
9
- * as runtime-only concerns absent from the static type.
10
- *
11
- * @typeParam T - The record shape.
12
- * @param record - The source object.
13
- * @param keys - The keys to exclude from the copy.
14
- * @returns A new object holding every own enumerable key of `record` except
15
- * those listed in `keys`.
4
+ * @param items The items to deduplicate.
5
+ * @param key Computes the identity string used to detect duplicates.
16
6
  */
17
- export const omit = (record, keys) => {
18
- const result = {};
19
- for (const key of Object.keys(record)) {
20
- if (!keys.includes(key)) {
21
- result[key] = record[key];
22
- }
7
+ export const uniqBy = (items, key) => {
8
+ const seen = new Set();
9
+ const result = [];
10
+ for (const item of items) {
11
+ const identity = key(item);
12
+ if (seen.has(identity))
13
+ continue;
14
+ seen.add(identity);
15
+ result.push(item);
23
16
  }
24
17
  return result;
25
18
  };
26
- /**
27
- * Compares two arrays of primitives for element-wise strict equality.
28
- *
29
- * Returns `true` when both arguments are the same reference (including both
30
- * being `null` or `undefined`), or when they have equal length and every
31
- * element is strictly equal (`===`) at the same index. A `null`/`undefined`
32
- * argument is equal only to another `null`/`undefined` argument.
33
- *
34
- * @typeParam T - The primitive element type.
35
- * @param a - The first array, or `null`/`undefined`.
36
- * @param b - The second array, or `null`/`undefined`.
37
- * @returns Whether the two arrays are shallowly equal.
38
- */
39
- export const isShallowEqual = (a, b) => {
40
- if (a === b)
41
- return true;
42
- if (!a || !b)
43
- return false;
19
+ export const isSameArray = (a, b) => {
44
20
  if (a.length !== b.length)
45
21
  return false;
46
- for (let i = 0; i < a.length; i++) {
47
- if (a[i] !== b[i])
22
+ for (let index = 0; index < a.length; index++) {
23
+ if (a[index] !== b[index])
48
24
  return false;
49
25
  }
50
26
  return true;
51
27
  };
28
+ const compareStrings = (a, b) => a.localeCompare(b);
29
+ /**
30
+ * Returns a new array of the given strings sorted with locale-aware comparison.
31
+ *
32
+ * @param values The strings to sort.
33
+ */
34
+ export const sortStrings = (values) => [...values].sort(compareStrings);
52
35
  /**
53
- * Compares two arrays of records by shallow per-element equality.
36
+ * Returns a new array of the given items sorted by a locale-aware comparison of their keys.
54
37
  *
55
- * Returns `true` when both arrays have equal length and, at every index, the
56
- * two records expose the same set of keys with strictly equal (`===`) values.
57
- * Values are compared one level deep only; nested objects are compared by
58
- * reference.
38
+ * @param items The items to sort.
39
+ * @param key Computes the string to sort each item by.
40
+ */
41
+ export const sortStringsBy = (items, key) => [...items].sort((a, b) => compareStrings(key(a), key(b)));
42
+ /**
43
+ * Determines whether two records have the same keys and strictly equal values.
59
44
  *
60
- * @typeParam T - The record element type.
61
- * @param a - The first array of records.
62
- * @param b - The second array of records.
63
- * @returns Whether the two arrays are element-wise shallowly equal.
45
+ * @param a The first record, or `undefined`.
46
+ * @param b The second record, or `undefined`.
47
+ * @returns `true` when both are the same reference, or both are defined with identical own keys and values.
64
48
  */
65
- export const isShallowArrayEqual = (a, b) => {
66
- if (a.length !== b.length)
49
+ export const isShallowEqual = (a, b) => {
50
+ if (a === b)
51
+ return true;
52
+ if (!a || !b)
67
53
  return false;
68
- for (let i = 0; i < a.length; i++) {
69
- const itemA = a[i];
70
- const itemB = b[i];
71
- if (!itemA || !itemB)
72
- return false;
73
- const keysA = Object.keys(itemA);
74
- const keysB = Object.keys(itemB);
75
- if (keysA.length !== keysB.length)
54
+ const keysA = Object.keys(a);
55
+ const keysB = Object.keys(b);
56
+ if (keysA.length !== keysB.length)
57
+ return false;
58
+ for (const key of keysA) {
59
+ if (a[key] !== b[key])
76
60
  return false;
77
- for (const key of keysA) {
78
- if (itemA[key] !== itemB[key])
79
- return false;
80
- }
81
61
  }
82
62
  return true;
83
63
  };
84
- /**
85
- * Builds a reverse lookup from a numeric enum's values to their member names.
86
- *
87
- * A TypeScript numeric enum's runtime object carries both name-to-value and
88
- * value-to-name entries; this keeps only the name-to-value direction and
89
- * inverts it, yielding a `Map` from each numeric value to the name that
90
- * declared it.
91
- *
92
- * @param enumObject - A numeric enum's runtime object.
93
- * @returns A map from each numeric enum value to its declared member name.
94
- */
95
- export const reverseNumericEnum = (enumObject) => new Map(Object.entries(enumObject)
96
- .filter((entry) => typeof entry[1] === "number")
97
- .map(([name, value]) => [value, name]));
98
64
  //# sourceMappingURL=collection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAoC,MAAS,EAAE,IAAuB,EAAK,EAAE;IAC7F,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IACD,OAAO,MAAW,CAAC;AACvB,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC1B,CAAkC,EAClC,CAAkC,EAC3B,EAAE;IACT,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAoC,CAAe,EAAE,CAAe,EAAW,EAAE;IAChH,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QAEnC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAEhD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;QAChD,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAA2C,EAAuB,EAAE,CACnG,IAAI,GAAG,CACH,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;KACrB,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;KAC1E,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAC7C,CAAC"}
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAI,KAAU,EAAE,GAAwB,EAAO,EAAE;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAI,CAAM,EAAE,CAAM,EAAW,EAAE;IACtD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAE5E;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAwB,EAAY,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAEpG;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAI,KAAkB,EAAE,GAAwB,EAAO,EAAE,CAClF,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAoC,CAAK,EAAE,CAAK,EAAW,EAAE;IACvF,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAEhD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IACxC,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC","sourcesContent":["/**\n * Returns the items with duplicates removed, keeping the first item for each distinct key.\n *\n * @param items The items to deduplicate.\n * @param key Computes the identity string used to detect duplicates.\n */\nexport const uniqBy = <T>(items: T[], key: (item: T) => string): T[] => {\n const seen = new Set<string>();\n const result: T[] = [];\n for (const item of items) {\n const identity = key(item);\n if (seen.has(identity)) continue;\n seen.add(identity);\n result.push(item);\n }\n return result;\n};\n\nexport const isSameArray = <T>(a: T[], b: T[]): boolean => {\n if (a.length !== b.length) return false;\n for (let index = 0; index < a.length; index++) {\n if (a[index] !== b[index]) return false;\n }\n return true;\n};\n\nconst compareStrings = (a: string, b: string): number => a.localeCompare(b);\n\n/**\n * Returns a new array of the given strings sorted with locale-aware comparison.\n *\n * @param values The strings to sort.\n */\nexport const sortStrings = (values: Iterable<string>): string[] => [...values].sort(compareStrings);\n\n/**\n * Returns a new array of the given items sorted by a locale-aware comparison of their keys.\n *\n * @param items The items to sort.\n * @param key Computes the string to sort each item by.\n */\nexport const sortStringsBy = <T>(items: Iterable<T>, key: (item: T) => string): T[] =>\n [...items].sort((a, b) => compareStrings(key(a), key(b)));\n\n/**\n * Determines whether two records have the same keys and strictly equal values.\n *\n * @param a The first record, or `undefined`.\n * @param b The second record, or `undefined`.\n * @returns `true` when both are the same reference, or both are defined with identical own keys and values.\n */\nexport const isShallowEqual = <T extends Record<string, unknown>>(a?: T, b?: T): boolean => {\n if (a === b) return true;\n if (!a || !b) return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false;\n }\n\n return true;\n};\n"]}
package/dist/error.d.ts CHANGED
@@ -1,13 +1,21 @@
1
1
  /**
2
- * Coerces an unknown thrown value into a human-readable string.
2
+ * Extracts a human-readable message from an unknown thrown value, falling back to its string form.
3
3
  *
4
- * Returns `error.message` when `error` is an `Error` instance, otherwise
5
- * delegates to `String(error)`. Use at boundaries where exceptions are
6
- * surfaced to logs, IPC frames, or user-facing output and the type cannot
7
- * be narrowed otherwise.
8
- *
9
- * @param error - The caught value of unknown shape.
10
- * @returns A string describing the error.
4
+ * @param error The caught value to describe.
11
5
  */
12
6
  export declare const errorMessage: (error: unknown) => string;
7
+ /**
8
+ * Coerces an unknown thrown value into an `Error`, reusing it if it already is one and otherwise
9
+ * wrapping its message while copying any error-like own properties.
10
+ *
11
+ * @param error The caught value to normalize.
12
+ */
13
+ export declare const normalizeError: (error: unknown) => Error;
14
+ /**
15
+ * Combines the `stderr` and `stdout` fields of a failed child-process error into a single trimmed string.
16
+ *
17
+ * @param error The child-process error to read output from.
18
+ * @returns The joined output, or `undefined` when neither stream carried any text.
19
+ */
20
+ export declare const formatChildProcessError: (error: unknown) => string | undefined;
13
21
  //# sourceMappingURL=error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,MAAkE,CAAC"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MACgC,CAAC;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAW,OAAO,KAAG,KAG/C,CAAC;AAQF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,UAAW,OAAO,KAAG,MAAM,GAAG,SAKjE,CAAC"}
package/dist/error.js CHANGED
@@ -1,13 +1,40 @@
1
+ const isObject = (value) => typeof value === "object" && value !== null;
2
+ const isErrorLike = (value) => isObject(value) && "message" in value && typeof value.message === "string";
1
3
  /**
2
- * Coerces an unknown thrown value into a human-readable string.
4
+ * Extracts a human-readable message from an unknown thrown value, falling back to its string form.
3
5
  *
4
- * Returns `error.message` when `error` is an `Error` instance, otherwise
5
- * delegates to `String(error)`. Use at boundaries where exceptions are
6
- * surfaced to logs, IPC frames, or user-facing output and the type cannot
7
- * be narrowed otherwise.
6
+ * @param error The caught value to describe.
7
+ */
8
+ export const errorMessage = (error) => Error.isError(error) || isErrorLike(error) ? error.message : String(error);
9
+ /**
10
+ * Coerces an unknown thrown value into an `Error`, reusing it if it already is one and otherwise
11
+ * wrapping its message while copying any error-like own properties.
12
+ *
13
+ * @param error The caught value to normalize.
14
+ */
15
+ export const normalizeError = (error) => {
16
+ if (Error.isError(error))
17
+ return error;
18
+ return Object.assign(new Error(errorMessage(error)), isErrorLike(error) ? error : {});
19
+ };
20
+ const readStream = (value) => {
21
+ if (typeof value === "string")
22
+ return value;
23
+ if (value instanceof Uint8Array || Buffer.isBuffer(value))
24
+ return value.toString();
25
+ return "";
26
+ };
27
+ /**
28
+ * Combines the `stderr` and `stdout` fields of a failed child-process error into a single trimmed string.
8
29
  *
9
- * @param error - The caught value of unknown shape.
10
- * @returns A string describing the error.
30
+ * @param error The child-process error to read output from.
31
+ * @returns The joined output, or `undefined` when neither stream carried any text.
11
32
  */
12
- export const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
33
+ export const formatChildProcessError = (error) => {
34
+ if (!isObject(error))
35
+ return undefined;
36
+ const { stderr, stdout } = error;
37
+ const details = [readStream(stderr), readStream(stdout)].filter(Boolean).join("\n").trim();
38
+ return details.length > 0 ? details : undefined;
39
+ };
13
40
  //# sourceMappingURL=error.js.map
package/dist/error.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAEnH,MAAM,WAAW,GAAG,CAAC,KAAc,EAAgC,EAAE,CACjE,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAU,EAAE,CACnD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAE/E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAc,EAAS,EAAE;IACpD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,KAAc,EAAU,EAAE;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,KAAK,YAAY,UAAU,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IACnF,OAAO,EAAE,CAAC;AACd,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAc,EAAsB,EAAE;IAC1E,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACjC,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3F,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACpD,CAAC,CAAC","sourcesContent":["const isObject = (value: unknown): value is Record<string, unknown> => typeof value === \"object\" && value !== null;\n\nconst isErrorLike = (value: unknown): value is { message: string } =>\n isObject(value) && \"message\" in value && typeof value.message === \"string\";\n\n/**\n * Extracts a human-readable message from an unknown thrown value, falling back to its string form.\n *\n * @param error The caught value to describe.\n */\nexport const errorMessage = (error: unknown): string =>\n Error.isError(error) || isErrorLike(error) ? error.message : String(error);\n\n/**\n * Coerces an unknown thrown value into an `Error`, reusing it if it already is one and otherwise\n * wrapping its message while copying any error-like own properties.\n *\n * @param error The caught value to normalize.\n */\nexport const normalizeError = (error: unknown): Error => {\n if (Error.isError(error)) return error;\n return Object.assign(new Error(errorMessage(error)), isErrorLike(error) ? error : {});\n};\n\nconst readStream = (value: unknown): string => {\n if (typeof value === \"string\") return value;\n if (value instanceof Uint8Array || Buffer.isBuffer(value)) return value.toString();\n return \"\";\n};\n\n/**\n * Combines the `stderr` and `stdout` fields of a failed child-process error into a single trimmed string.\n *\n * @param error The child-process error to read output from.\n * @returns The joined output, or `undefined` when neither stream carried any text.\n */\nexport const formatChildProcessError = (error: unknown): string | undefined => {\n if (!isObject(error)) return undefined;\n const { stderr, stdout } = error;\n const details = [readStream(stderr), readStream(stdout)].filter(Boolean).join(\"\\n\").trim();\n return details.length > 0 ? details : undefined;\n};\n"]}