@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.
- package/README.md +173 -0
- package/dist/class.d.ts +17 -11
- package/dist/class.d.ts.map +1 -1
- package/dist/class.js +27 -1
- package/dist/class.js.map +1 -1
- package/dist/collection.d.ts +17 -45
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +42 -76
- package/dist/collection.js.map +1 -1
- package/dist/error.d.ts +16 -8
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +35 -8
- package/dist/error.js.map +1 -1
- package/dist/graceful-shutdown.d.ts +9 -57
- package/dist/graceful-shutdown.d.ts.map +1 -1
- package/dist/graceful-shutdown.js +70 -75
- package/dist/graceful-shutdown.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts +103 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +129 -0
- package/dist/log.js.map +1 -0
- package/dist/package-version.d.ts +7 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +8 -0
- package/dist/package-version.js.map +1 -0
- package/dist/reflect.d.ts +11 -0
- package/dist/reflect.d.ts.map +1 -0
- package/dist/reflect.js +14 -0
- package/dist/reflect.js.map +1 -0
- package/dist/source.d.ts +12 -25
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +20 -41
- package/dist/source.js.map +1 -1
- package/dist/string.d.ts +13 -40
- package/dist/string.d.ts.map +1 -1
- package/dist/string.js +18 -48
- package/dist/string.js.map +1 -1
- package/package.json +20 -7
- package/src/class.ts +30 -11
- package/src/collection.ts +43 -81
- package/src/error.ts +38 -8
- package/src/graceful-shutdown.ts +87 -114
- package/src/index.ts +18 -9
- package/src/log.ts +164 -0
- package/src/package-version.ts +9 -0
- package/src/reflect.ts +13 -0
- package/src/source.ts +24 -43
- package/src/string.ts +19 -47
package/dist/reflect.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls the named method on `target` with the given arguments, returning `undefined` when the
|
|
3
|
+
* property is missing or not callable.
|
|
4
|
+
*
|
|
5
|
+
* @param target The object to read the method from and bind as `this`.
|
|
6
|
+
* @param method The method name to look up.
|
|
7
|
+
* @param args Arguments passed to the method.
|
|
8
|
+
* @returns The method's return value, or `undefined` when it is not a function.
|
|
9
|
+
*/
|
|
10
|
+
export const callMethod = (target, method, args) => {
|
|
11
|
+
const fn = Reflect.get(target, method);
|
|
12
|
+
return typeof fn === "function" ? Reflect.apply(fn, target, args) : undefined;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=reflect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflect.js","sourceRoot":"","sources":["../src/reflect.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,MAAc,EAAE,IAAe,EAAW,EAAE;IACnF,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,OAAO,OAAO,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAClF,CAAC,CAAC","sourcesContent":["/**\n * Calls the named method on `target` with the given arguments, returning `undefined` when the\n * property is missing or not callable.\n *\n * @param target The object to read the method from and bind as `this`.\n * @param method The method name to look up.\n * @param args Arguments passed to the method.\n * @returns The method's return value, or `undefined` when it is not a function.\n */\nexport const callMethod = (target: object, method: string, args: unknown[]): unknown => {\n const fn = Reflect.get(target, method);\n return typeof fn === \"function\" ? Reflect.apply(fn, target, args) : undefined;\n};\n"]}
|
package/dist/source.d.ts
CHANGED
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Returns the name unchanged, or with a trailing underscore when it collides with a reserved word,
|
|
3
|
+
* so it is safe to emit as a JavaScript identifier.
|
|
4
|
+
*
|
|
5
|
+
* @param name The candidate identifier.
|
|
5
6
|
*/
|
|
7
|
+
export declare const sanitizeIdentifier: (name: string) => string;
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
8
|
-
* variable, parameter, or property position.
|
|
9
|
-
*
|
|
10
|
-
* The input is expected to already use valid identifier characters (for
|
|
11
|
-
* example the output of a case-conversion helper); the only transformation
|
|
12
|
-
* applied is appending an underscore when `name` collides with a reserved
|
|
13
|
-
* word or global identifier, so `toIdentifier("class")` is `"class_"` and
|
|
14
|
-
* `toIdentifier("iconName")` is `"iconName"`.
|
|
9
|
+
* Converts a name to camelCase and sanitizes it into a valid JavaScript identifier.
|
|
15
10
|
*
|
|
16
|
-
* @param name
|
|
17
|
-
* @returns A reserved-word-safe identifier.
|
|
11
|
+
* @param name The name to convert.
|
|
18
12
|
*/
|
|
19
|
-
export declare const
|
|
13
|
+
export declare const toCamelIdentifier: (name: string) => string;
|
|
20
14
|
/**
|
|
21
|
-
*
|
|
22
|
-
* source.
|
|
23
|
-
*
|
|
24
|
-
* Builds a double-quoted literal with `JSON.stringify`, then escapes the
|
|
25
|
-
* characters that are valid inside a JSON string yet unsafe inside JavaScript
|
|
26
|
-
* source: the angle brackets that could otherwise break out of an enclosing
|
|
27
|
-
* `</script>` and the U+2028/U+2029 line separators that prematurely terminate
|
|
28
|
-
* a string literal. The escaped form parses back to the original value.
|
|
15
|
+
* Encodes a string as a JavaScript string literal, additionally escaping characters that are unsafe
|
|
16
|
+
* to embed in generated source (angle brackets and the line and paragraph separators).
|
|
29
17
|
*
|
|
30
|
-
* @param value
|
|
31
|
-
* @returns A source-safe double-quoted string literal.
|
|
18
|
+
* @param value The string to encode.
|
|
32
19
|
*/
|
|
33
|
-
export declare const
|
|
20
|
+
export declare const sourceStringLiteral: (value: string) => string;
|
|
34
21
|
//# sourceMappingURL=source.d.ts.map
|
package/dist/source.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAoDA;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,SAAU,MAAM,KAAG,MAAkD,CAAC;AAErG;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,KAAG,MAA+C,CAAC;AAWjG;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,UAAW,MAAM,KAAG,MAC0C,CAAC"}
|
package/dist/source.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Helpers for shaping values into safe JavaScript/TypeScript source fragments:
|
|
3
|
-
* a reserved-word-safe identifier and a source-safe string literal. Both are
|
|
4
|
-
* pure and runtime-agnostic, intended for code generators that emit TypeScript.
|
|
5
|
-
*/
|
|
6
|
-
/** Reserved words and global identifiers a generated identifier must not collide with. */
|
|
1
|
+
import { toCamelCase } from "./string.js";
|
|
7
2
|
const RESERVED = new Set([
|
|
8
3
|
"arguments",
|
|
9
4
|
"await",
|
|
@@ -54,46 +49,30 @@ const RESERVED = new Set([
|
|
|
54
49
|
"yield",
|
|
55
50
|
]);
|
|
56
51
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
52
|
+
* Returns the name unchanged, or with a trailing underscore when it collides with a reserved word,
|
|
53
|
+
* so it is safe to emit as a JavaScript identifier.
|
|
59
54
|
*
|
|
60
|
-
*
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*
|
|
55
|
+
* @param name The candidate identifier.
|
|
56
|
+
*/
|
|
57
|
+
export const sanitizeIdentifier = (name) => (RESERVED.has(name) ? `${name}_` : name);
|
|
58
|
+
/**
|
|
59
|
+
* Converts a name to camelCase and sanitizes it into a valid JavaScript identifier.
|
|
65
60
|
*
|
|
66
|
-
* @param name
|
|
67
|
-
* @returns A reserved-word-safe identifier.
|
|
61
|
+
* @param name The name to convert.
|
|
68
62
|
*/
|
|
69
|
-
export const
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
case ">":
|
|
76
|
-
return "\\u003E";
|
|
77
|
-
case "\u2028":
|
|
78
|
-
return "\\u2028";
|
|
79
|
-
case "\u2029":
|
|
80
|
-
return "\\u2029";
|
|
81
|
-
default:
|
|
82
|
-
return char;
|
|
83
|
-
}
|
|
63
|
+
export const toCamelIdentifier = (name) => sanitizeIdentifier(toCamelCase(name));
|
|
64
|
+
const SOURCE_ESCAPES = {
|
|
65
|
+
"<": "\\u003C",
|
|
66
|
+
">": "\\u003E",
|
|
67
|
+
"\u2028": "\\u2028",
|
|
68
|
+
"\u2029": "\\u2029",
|
|
84
69
|
};
|
|
70
|
+
const UNSAFE_SOURCE_CHARS = new RegExp(`[${Object.keys(SOURCE_ESCAPES).join("")}]`, "g");
|
|
85
71
|
/**
|
|
86
|
-
*
|
|
87
|
-
* source.
|
|
88
|
-
*
|
|
89
|
-
* Builds a double-quoted literal with `JSON.stringify`, then escapes the
|
|
90
|
-
* characters that are valid inside a JSON string yet unsafe inside JavaScript
|
|
91
|
-
* source: the angle brackets that could otherwise break out of an enclosing
|
|
92
|
-
* `</script>` and the U+2028/U+2029 line separators that prematurely terminate
|
|
93
|
-
* a string literal. The escaped form parses back to the original value.
|
|
72
|
+
* Encodes a string as a JavaScript string literal, additionally escaping characters that are unsafe
|
|
73
|
+
* to embed in generated source (angle brackets and the line and paragraph separators).
|
|
94
74
|
*
|
|
95
|
-
* @param value
|
|
96
|
-
* @returns A source-safe double-quoted string literal.
|
|
75
|
+
* @param value The string to encode.
|
|
97
76
|
*/
|
|
98
|
-
export const
|
|
77
|
+
export const sourceStringLiteral = (value) => JSON.stringify(value).replace(UNSAFE_SOURCE_CHARS, (char) => SOURCE_ESCAPES[char] ?? char);
|
|
99
78
|
//# sourceMappingURL=source.js.map
|
package/dist/source.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,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;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAErG;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;AAEjG,MAAM,cAAc,GAA2B;IAC3C,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;CACtB,CAAC;AAEF,MAAM,mBAAmB,GAAG,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAa,EAAU,EAAE,CACzD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC","sourcesContent":["import { toCamelCase } from \"./string.js\";\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 \"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\n/**\n * Returns the name unchanged, or with a trailing underscore when it collides with a reserved word,\n * so it is safe to emit as a JavaScript identifier.\n *\n * @param name The candidate identifier.\n */\nexport const sanitizeIdentifier = (name: string): string => (RESERVED.has(name) ? `${name}_` : name);\n\n/**\n * Converts a name to camelCase and sanitizes it into a valid JavaScript identifier.\n *\n * @param name The name to convert.\n */\nexport const toCamelIdentifier = (name: string): string => sanitizeIdentifier(toCamelCase(name));\n\nconst SOURCE_ESCAPES: Record<string, string> = {\n \"<\": \"\\\\u003C\",\n \">\": \"\\\\u003E\",\n \"\\u2028\": \"\\\\u2028\",\n \"\\u2029\": \"\\\\u2029\",\n};\n\nconst UNSAFE_SOURCE_CHARS = new RegExp(`[${Object.keys(SOURCE_ESCAPES).join(\"\")}]`, \"g\");\n\n/**\n * Encodes a string as a JavaScript string literal, additionally escaping characters that are unsafe\n * to embed in generated source (angle brackets and the line and paragraph separators).\n *\n * @param value The string to encode.\n */\nexport const sourceStringLiteral = (value: string): string =>\n JSON.stringify(value).replace(UNSAFE_SOURCE_CHARS, (char) => SOURCE_ESCAPES[char] ?? char);\n"]}
|
package/dist/string.d.ts
CHANGED
|
@@ -1,59 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Returns the string with its first character uppercased.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* PascalCase. They split only on underscores and hyphens and preserve the case
|
|
6
|
-
* of each segment, so they are not a substitute for a full Unicode-aware case
|
|
7
|
-
* transform.
|
|
4
|
+
* @param value The string to transform.
|
|
8
5
|
*/
|
|
6
|
+
export declare const upperFirst: (value: string) => string;
|
|
9
7
|
/**
|
|
10
|
-
*
|
|
11
|
-
* untouched.
|
|
8
|
+
* Returns the string with its first character lowercased.
|
|
12
9
|
*
|
|
13
|
-
*
|
|
14
|
-
* `toUpperFirst("fooBar")` is `"FooBar"` and `toUpperFirst("URL")` is `"URL"`. An
|
|
15
|
-
* empty string returns an empty string.
|
|
16
|
-
*
|
|
17
|
-
* @param value - The string to transform.
|
|
18
|
-
* @returns `value` with its first character uppercased.
|
|
10
|
+
* @param value The string to transform.
|
|
19
11
|
*/
|
|
20
|
-
export declare const
|
|
12
|
+
export declare const lowerFirst: (value: string) => string;
|
|
21
13
|
/**
|
|
22
|
-
* Converts
|
|
23
|
-
*
|
|
24
|
-
* The input is split on underscores and hyphens, dropping empty segments from
|
|
25
|
-
* leading, trailing, or repeated separators. The first segment is kept
|
|
26
|
-
* verbatim and every later segment is {@link toUpperFirst}-cased before joining,
|
|
27
|
-
* so `toCamelCase("icon_name")` is `"iconName"` and `toCamelCase("Box")` is
|
|
28
|
-
* `"Box"`. A string with no separators is returned unchanged.
|
|
14
|
+
* Converts an underscore- or hyphen-delimited string to camelCase.
|
|
29
15
|
*
|
|
30
|
-
* @param input
|
|
31
|
-
* @returns The camelCase form of `input`.
|
|
16
|
+
* @param input The string to convert.
|
|
32
17
|
*/
|
|
33
18
|
export declare const toCamelCase: (input: string) => string;
|
|
34
19
|
/**
|
|
35
|
-
* Converts
|
|
36
|
-
* PascalCase.
|
|
20
|
+
* Converts an underscore- or hyphen-delimited string to PascalCase.
|
|
37
21
|
*
|
|
38
|
-
*
|
|
39
|
-
* every remaining segment is {@link toUpperFirst}-cased before joining, so
|
|
40
|
-
* `toPascalCase("icon_name")` is `"IconName"` and `toPascalCase("Box")` is
|
|
41
|
-
* `"Box"`. An empty string is returned unchanged.
|
|
42
|
-
*
|
|
43
|
-
* @param input - The identifier to transform.
|
|
44
|
-
* @returns The PascalCase form of `input`.
|
|
22
|
+
* @param input The string to convert.
|
|
45
23
|
*/
|
|
46
24
|
export declare const toPascalCase: (input: string) => string;
|
|
47
25
|
/**
|
|
48
|
-
* Converts a camelCase or PascalCase string to kebab-case
|
|
49
|
-
*
|
|
50
|
-
* Each uppercase character is lowercased; every uppercase character other than
|
|
51
|
-
* the first is additionally prefixed with a hyphen, so `toKebabCase("iconName")`
|
|
52
|
-
* is `"icon-name"` and `toKebabCase("Title")` is `"title"`. The leading
|
|
53
|
-
* character is never prefixed with a hyphen.
|
|
26
|
+
* Converts a camelCase or PascalCase string to kebab-case by lowercasing uppercase letters and
|
|
27
|
+
* inserting hyphens before interior ones.
|
|
54
28
|
*
|
|
55
|
-
* @param input
|
|
56
|
-
* @returns The kebab-case form of `input`.
|
|
29
|
+
* @param input The string to convert.
|
|
57
30
|
*/
|
|
58
31
|
export declare const toKebabCase: (input: string) => string;
|
|
59
32
|
//# sourceMappingURL=string.d.ts.map
|
package/dist/string.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,MAAwD,CAAC;AAEpG;;;;GAIG;AACH,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,MAAwD,CAAC;AAIpG;;;;GAIG;AACH,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,MAI3C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,MAAM,KAAG,MAI5C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,MAC0E,CAAC"}
|
package/dist/string.js
CHANGED
|
@@ -1,73 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Returns the string with its first character uppercased.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* PascalCase. They split only on underscores and hyphens and preserve the case
|
|
6
|
-
* of each segment, so they are not a substitute for a full Unicode-aware case
|
|
7
|
-
* transform.
|
|
4
|
+
* @param value The string to transform.
|
|
8
5
|
*/
|
|
6
|
+
export const upperFirst = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
9
7
|
/**
|
|
10
|
-
*
|
|
11
|
-
* untouched.
|
|
8
|
+
* Returns the string with its first character lowercased.
|
|
12
9
|
*
|
|
13
|
-
*
|
|
14
|
-
* `toUpperFirst("fooBar")` is `"FooBar"` and `toUpperFirst("URL")` is `"URL"`. An
|
|
15
|
-
* empty string returns an empty string.
|
|
16
|
-
*
|
|
17
|
-
* @param value - The string to transform.
|
|
18
|
-
* @returns `value` with its first character uppercased.
|
|
10
|
+
* @param value The string to transform.
|
|
19
11
|
*/
|
|
20
|
-
export const
|
|
12
|
+
export const lowerFirst = (value) => value.charAt(0).toLowerCase() + value.slice(1);
|
|
13
|
+
const splitWords = (input) => input.split(/[_-]/g).filter((part) => part.length > 0);
|
|
21
14
|
/**
|
|
22
|
-
* Converts
|
|
23
|
-
*
|
|
24
|
-
* The input is split on underscores and hyphens, dropping empty segments from
|
|
25
|
-
* leading, trailing, or repeated separators. The first segment is kept
|
|
26
|
-
* verbatim and every later segment is {@link toUpperFirst}-cased before joining,
|
|
27
|
-
* so `toCamelCase("icon_name")` is `"iconName"` and `toCamelCase("Box")` is
|
|
28
|
-
* `"Box"`. A string with no separators is returned unchanged.
|
|
15
|
+
* Converts an underscore- or hyphen-delimited string to camelCase.
|
|
29
16
|
*
|
|
30
|
-
* @param input
|
|
31
|
-
* @returns The camelCase form of `input`.
|
|
17
|
+
* @param input The string to convert.
|
|
32
18
|
*/
|
|
33
19
|
export const toCamelCase = (input) => {
|
|
34
|
-
const parts = input
|
|
20
|
+
const parts = splitWords(input);
|
|
35
21
|
if (parts.length === 0)
|
|
36
22
|
return input;
|
|
37
|
-
|
|
38
|
-
const head = first ?? "";
|
|
39
|
-
return head + rest.map(toUpperFirst).join("");
|
|
23
|
+
return parts.map((part, index) => (index === 0 ? part : upperFirst(part))).join("");
|
|
40
24
|
};
|
|
41
25
|
/**
|
|
42
|
-
* Converts
|
|
43
|
-
* PascalCase.
|
|
44
|
-
*
|
|
45
|
-
* The input is split on underscores and hyphens, dropping empty segments, and
|
|
46
|
-
* every remaining segment is {@link toUpperFirst}-cased before joining, so
|
|
47
|
-
* `toPascalCase("icon_name")` is `"IconName"` and `toPascalCase("Box")` is
|
|
48
|
-
* `"Box"`. An empty string is returned unchanged.
|
|
26
|
+
* Converts an underscore- or hyphen-delimited string to PascalCase.
|
|
49
27
|
*
|
|
50
|
-
* @param input
|
|
51
|
-
* @returns The PascalCase form of `input`.
|
|
28
|
+
* @param input The string to convert.
|
|
52
29
|
*/
|
|
53
30
|
export const toPascalCase = (input) => {
|
|
54
|
-
|
|
55
|
-
return input;
|
|
56
|
-
const parts = input.split(/[_-]/g).filter((part) => part.length > 0);
|
|
31
|
+
const parts = splitWords(input);
|
|
57
32
|
if (parts.length === 0)
|
|
58
33
|
return input;
|
|
59
|
-
return parts.map(
|
|
34
|
+
return parts.map(upperFirst).join("");
|
|
60
35
|
};
|
|
61
36
|
/**
|
|
62
|
-
* Converts a camelCase or PascalCase string to kebab-case
|
|
63
|
-
*
|
|
64
|
-
* Each uppercase character is lowercased; every uppercase character other than
|
|
65
|
-
* the first is additionally prefixed with a hyphen, so `toKebabCase("iconName")`
|
|
66
|
-
* is `"icon-name"` and `toKebabCase("Title")` is `"title"`. The leading
|
|
67
|
-
* character is never prefixed with a hyphen.
|
|
37
|
+
* Converts a camelCase or PascalCase string to kebab-case by lowercasing uppercase letters and
|
|
38
|
+
* inserting hyphens before interior ones.
|
|
68
39
|
*
|
|
69
|
-
* @param input
|
|
70
|
-
* @returns The kebab-case form of `input`.
|
|
40
|
+
* @param input The string to convert.
|
|
71
41
|
*/
|
|
72
42
|
export const toKebabCase = (input) => input.replaceAll(/[A-Z]/g, (char, index) => (index === 0 ? char.toLowerCase() : `-${char.toLowerCase()}`));
|
|
73
43
|
//# sourceMappingURL=string.js.map
|
package/dist/string.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEpG;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEpG,MAAM,UAAU,GAAG,CAAC,KAAa,EAAY,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAEvG;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxF,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE;IAClD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE,CACjD,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Returns the string with its first character uppercased.\n *\n * @param value The string to transform.\n */\nexport const upperFirst = (value: string): string => value.charAt(0).toUpperCase() + value.slice(1);\n\n/**\n * Returns the string with its first character lowercased.\n *\n * @param value The string to transform.\n */\nexport const lowerFirst = (value: string): string => value.charAt(0).toLowerCase() + value.slice(1);\n\nconst splitWords = (input: string): string[] => input.split(/[_-]/g).filter((part) => part.length > 0);\n\n/**\n * Converts an underscore- or hyphen-delimited string to camelCase.\n *\n * @param input The string to convert.\n */\nexport const toCamelCase = (input: string): string => {\n const parts = splitWords(input);\n if (parts.length === 0) return input;\n return parts.map((part, index) => (index === 0 ? part : upperFirst(part))).join(\"\");\n};\n\n/**\n * Converts an underscore- or hyphen-delimited string to PascalCase.\n *\n * @param input The string to convert.\n */\nexport const toPascalCase = (input: string): string => {\n const parts = splitWords(input);\n if (parts.length === 0) return input;\n return parts.map(upperFirst).join(\"\");\n};\n\n/**\n * Converts a camelCase or PascalCase string to kebab-case by lowercasing uppercase letters and\n * inserting hyphens before interior ones.\n *\n * @param input The string to convert.\n */\nexport const toKebabCase = (input: string): string =>\n input.replaceAll(/[A-Z]/g, (char, index: number) => (index === 0 ? char.toLowerCase() : `-${char.toLowerCase()}`));\n"]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/utils",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Cross-package utilities shared by GTKX
|
|
3
|
+
"version": "1.0.0-rc.1",
|
|
4
|
+
"description": "Cross-package utilities shared by the GTKX packages and toolchain: logging, error formatting, string and class helpers",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"gtkx",
|
|
7
|
+
"gtk",
|
|
8
|
+
"gtk4",
|
|
9
|
+
"utils",
|
|
10
|
+
"linux",
|
|
11
|
+
"desktop"
|
|
12
|
+
],
|
|
5
13
|
"homepage": "https://gtkx.dev",
|
|
6
14
|
"bugs": {
|
|
7
15
|
"url": "https://github.com/gtkx-org/gtkx/issues"
|
|
8
16
|
},
|
|
9
17
|
"repository": {
|
|
10
18
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/gtkx-org/gtkx.git",
|
|
19
|
+
"url": "git+https://github.com/gtkx-org/gtkx.git",
|
|
12
20
|
"directory": "packages/utils"
|
|
13
21
|
},
|
|
14
22
|
"license": "MPL-2.0",
|
|
@@ -17,7 +25,6 @@
|
|
|
17
25
|
"exports": {
|
|
18
26
|
"./package.json": "./package.json",
|
|
19
27
|
".": {
|
|
20
|
-
"source": "./src/index.ts",
|
|
21
28
|
"types": "./dist/index.d.ts",
|
|
22
29
|
"default": "./dist/index.js"
|
|
23
30
|
}
|
|
@@ -27,9 +34,15 @@
|
|
|
27
34
|
"dist",
|
|
28
35
|
"src"
|
|
29
36
|
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"picocolors": "^1.1.1"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=24"
|
|
42
|
+
},
|
|
30
43
|
"scripts": {
|
|
31
|
-
"build": "tsc -b",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
44
|
+
"build": "tsc -b tsconfig.lib.json",
|
|
45
|
+
"typecheck": "tsc -b --emitDeclarationOnly",
|
|
46
|
+
"release": "tsx ../../scripts/release-package.ts"
|
|
34
47
|
}
|
|
35
48
|
}
|
package/src/class.ts
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
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 (
|
|
14
5
|
...args: never[]
|
|
15
6
|
) => T) & {
|
|
16
|
-
|
|
7
|
+
prototype: T;
|
|
17
8
|
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns the direct superclass of `cls`, or `null` when it has no class ancestor.
|
|
12
|
+
*
|
|
13
|
+
* @param cls The class whose prototype parent to inspect.
|
|
14
|
+
*/
|
|
15
|
+
export function getParentClass(cls: AnyClass): AnyClass | null {
|
|
16
|
+
const parent: unknown = Object.getPrototypeOf(cls);
|
|
17
|
+
return typeof parent === "function" && parent !== Function.prototype ? (parent as AnyClass) : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Walks the class chain from `cls` up through its ancestors, calling `visit` on each and
|
|
22
|
+
* returning the first result that is not `undefined`.
|
|
23
|
+
*
|
|
24
|
+
* @param cls The class to start from, or `null` to visit nothing.
|
|
25
|
+
* @param visit Called with each class in the chain; a defined return value stops the walk.
|
|
26
|
+
* @returns The first defined result from `visit`, or `undefined` if none was produced.
|
|
27
|
+
*/
|
|
28
|
+
export function walkClassChain<T>(cls: AnyClass | null, visit: (ancestor: AnyClass) => T | undefined): T | undefined {
|
|
29
|
+
let current = cls;
|
|
30
|
+
while (current !== null) {
|
|
31
|
+
const result = visit(current);
|
|
32
|
+
if (result !== undefined) return result;
|
|
33
|
+
current = getParentClass(current);
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
package/src/collection.ts
CHANGED
|
@@ -1,103 +1,65 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Returns a shallow copy of `record` with the given `keys` removed.
|
|
7
|
-
*
|
|
8
|
-
* Keys absent from `record` are ignored, and `record` is not mutated. The
|
|
9
|
-
* result is typed as the input shape because callers treat the excluded keys
|
|
10
|
-
* as runtime-only concerns absent from the static type.
|
|
2
|
+
* Returns the items with duplicates removed, keeping the first item for each distinct key.
|
|
11
3
|
*
|
|
12
|
-
* @
|
|
13
|
-
* @param
|
|
14
|
-
* @param keys - The keys to exclude from the copy.
|
|
15
|
-
* @returns A new object holding every own enumerable key of `record` except
|
|
16
|
-
* those listed in `keys`.
|
|
4
|
+
* @param items The items to deduplicate.
|
|
5
|
+
* @param key Computes the identity string used to detect duplicates.
|
|
17
6
|
*/
|
|
18
|
-
export const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
export const uniqBy = <T>(items: T[], key: (item: T) => string): T[] => {
|
|
8
|
+
const seen = new Set<string>();
|
|
9
|
+
const result: T[] = [];
|
|
10
|
+
for (const item of items) {
|
|
11
|
+
const identity = key(item);
|
|
12
|
+
if (seen.has(identity)) continue;
|
|
13
|
+
seen.add(identity);
|
|
14
|
+
result.push(item);
|
|
24
15
|
}
|
|
25
|
-
return result
|
|
16
|
+
return result;
|
|
26
17
|
};
|
|
27
18
|
|
|
28
|
-
|
|
29
|
-
* Compares two arrays of primitives for element-wise strict equality.
|
|
30
|
-
*
|
|
31
|
-
* Returns `true` when both arguments are the same reference (including both
|
|
32
|
-
* being `null` or `undefined`), or when they have equal length and every
|
|
33
|
-
* element is strictly equal (`===`) at the same index. A `null`/`undefined`
|
|
34
|
-
* argument is equal only to another `null`/`undefined` argument.
|
|
35
|
-
*
|
|
36
|
-
* @typeParam T - The primitive element type.
|
|
37
|
-
* @param a - The first array, or `null`/`undefined`.
|
|
38
|
-
* @param b - The second array, or `null`/`undefined`.
|
|
39
|
-
* @returns Whether the two arrays are shallowly equal.
|
|
40
|
-
*/
|
|
41
|
-
export const isShallowEqual = <T extends string | number | boolean>(
|
|
42
|
-
a: readonly T[] | null | undefined,
|
|
43
|
-
b: readonly T[] | null | undefined,
|
|
44
|
-
): boolean => {
|
|
45
|
-
if (a === b) return true;
|
|
46
|
-
if (!a || !b) return false;
|
|
19
|
+
export const isSameArray = <T>(a: T[], b: T[]): boolean => {
|
|
47
20
|
if (a.length !== b.length) return false;
|
|
48
|
-
for (let
|
|
49
|
-
if (a[
|
|
21
|
+
for (let index = 0; index < a.length; index++) {
|
|
22
|
+
if (a[index] !== b[index]) return false;
|
|
50
23
|
}
|
|
51
24
|
return true;
|
|
52
25
|
};
|
|
53
26
|
|
|
27
|
+
const compareStrings = (a: string, b: string): number => a.localeCompare(b);
|
|
28
|
+
|
|
54
29
|
/**
|
|
55
|
-
*
|
|
30
|
+
* Returns a new array of the given strings sorted with locale-aware comparison.
|
|
56
31
|
*
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
32
|
+
* @param values The strings to sort.
|
|
33
|
+
*/
|
|
34
|
+
export const sortStrings = (values: Iterable<string>): string[] => [...values].sort(compareStrings);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns a new array of the given items sorted by a locale-aware comparison of their keys.
|
|
61
38
|
*
|
|
62
|
-
* @
|
|
63
|
-
* @param
|
|
64
|
-
* @param b - The second array of records.
|
|
65
|
-
* @returns Whether the two arrays are element-wise shallowly equal.
|
|
39
|
+
* @param items The items to sort.
|
|
40
|
+
* @param key Computes the string to sort each item by.
|
|
66
41
|
*/
|
|
67
|
-
export const
|
|
68
|
-
|
|
42
|
+
export const sortStringsBy = <T>(items: Iterable<T>, key: (item: T) => string): T[] =>
|
|
43
|
+
[...items].sort((a, b) => compareStrings(key(a), key(b)));
|
|
69
44
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Determines whether two records have the same keys and strictly equal values.
|
|
47
|
+
*
|
|
48
|
+
* @param a The first record, or `undefined`.
|
|
49
|
+
* @param b The second record, or `undefined`.
|
|
50
|
+
* @returns `true` when both are the same reference, or both are defined with identical own keys and values.
|
|
51
|
+
*/
|
|
52
|
+
export const isShallowEqual = <T extends Record<string, unknown>>(a?: T, b?: T): boolean => {
|
|
53
|
+
if (a === b) return true;
|
|
54
|
+
if (!a || !b) return false;
|
|
74
55
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
56
|
+
const keysA = Object.keys(a);
|
|
57
|
+
const keysB = Object.keys(b);
|
|
58
|
+
if (keysA.length !== keysB.length) return false;
|
|
78
59
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
60
|
+
for (const key of keysA) {
|
|
61
|
+
if (a[key] !== b[key]) return false;
|
|
82
62
|
}
|
|
83
63
|
|
|
84
64
|
return true;
|
|
85
65
|
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Builds a reverse lookup from a numeric enum's values to their member names.
|
|
89
|
-
*
|
|
90
|
-
* A TypeScript numeric enum's runtime object carries both name-to-value and
|
|
91
|
-
* value-to-name entries; this keeps only the name-to-value direction and
|
|
92
|
-
* inverts it, yielding a `Map` from each numeric value to the name that
|
|
93
|
-
* declared it.
|
|
94
|
-
*
|
|
95
|
-
* @param enumObject - A numeric enum's runtime object.
|
|
96
|
-
* @returns A map from each numeric enum value to its declared member name.
|
|
97
|
-
*/
|
|
98
|
-
export const reverseNumericEnum = (enumObject: Record<string, string | number>): Map<number, string> =>
|
|
99
|
-
new Map<number, string>(
|
|
100
|
-
Object.entries(enumObject)
|
|
101
|
-
.filter((entry): entry is [string, number] => typeof entry[1] === "number")
|
|
102
|
-
.map(([name, value]) => [value, name]),
|
|
103
|
-
);
|