@fuzdev/fuz_util 0.42.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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/array.d.ts +15 -0
  4. package/dist/array.d.ts.map +1 -0
  5. package/dist/array.js +25 -0
  6. package/dist/async.d.ts +62 -0
  7. package/dist/async.d.ts.map +1 -0
  8. package/dist/async.js +147 -0
  9. package/dist/colors.d.ts +41 -0
  10. package/dist/colors.d.ts.map +1 -0
  11. package/dist/colors.js +106 -0
  12. package/dist/counter.d.ts +7 -0
  13. package/dist/counter.d.ts.map +1 -0
  14. package/dist/counter.js +7 -0
  15. package/dist/deep_equal.d.ts +18 -0
  16. package/dist/deep_equal.d.ts.map +1 -0
  17. package/dist/deep_equal.js +152 -0
  18. package/dist/dom.d.ts +35 -0
  19. package/dist/dom.d.ts.map +1 -0
  20. package/dist/dom.js +95 -0
  21. package/dist/error.d.ts +15 -0
  22. package/dist/error.d.ts.map +1 -0
  23. package/dist/error.js +18 -0
  24. package/dist/fetch.d.ts +81 -0
  25. package/dist/fetch.d.ts.map +1 -0
  26. package/dist/fetch.js +162 -0
  27. package/dist/fs.d.ts +34 -0
  28. package/dist/fs.d.ts.map +1 -0
  29. package/dist/fs.js +73 -0
  30. package/dist/function.d.ts +27 -0
  31. package/dist/function.d.ts.map +1 -0
  32. package/dist/function.js +21 -0
  33. package/dist/git.d.ts +132 -0
  34. package/dist/git.d.ts.map +1 -0
  35. package/dist/git.js +288 -0
  36. package/dist/id.d.ts +18 -0
  37. package/dist/id.d.ts.map +1 -0
  38. package/dist/id.js +18 -0
  39. package/dist/iterator.d.ts +5 -0
  40. package/dist/iterator.d.ts.map +1 -0
  41. package/dist/iterator.js +9 -0
  42. package/dist/json.d.ts +30 -0
  43. package/dist/json.d.ts.map +1 -0
  44. package/dist/json.js +44 -0
  45. package/dist/library_json.d.ts +42 -0
  46. package/dist/library_json.d.ts.map +1 -0
  47. package/dist/library_json.js +76 -0
  48. package/dist/log.d.ts +188 -0
  49. package/dist/log.d.ts.map +1 -0
  50. package/dist/log.js +393 -0
  51. package/dist/map.d.ts +12 -0
  52. package/dist/map.d.ts.map +1 -0
  53. package/dist/map.js +14 -0
  54. package/dist/maths.d.ts +85 -0
  55. package/dist/maths.d.ts.map +1 -0
  56. package/dist/maths.js +87 -0
  57. package/dist/object.d.ts +46 -0
  58. package/dist/object.d.ts.map +1 -0
  59. package/dist/object.js +89 -0
  60. package/dist/package_json.d.ts +90 -0
  61. package/dist/package_json.d.ts.map +1 -0
  62. package/dist/package_json.js +112 -0
  63. package/dist/path.d.ts +63 -0
  64. package/dist/path.d.ts.map +1 -0
  65. package/dist/path.js +83 -0
  66. package/dist/print.d.ts +52 -0
  67. package/dist/print.d.ts.map +1 -0
  68. package/dist/print.js +89 -0
  69. package/dist/process.d.ts +77 -0
  70. package/dist/process.d.ts.map +1 -0
  71. package/dist/process.js +148 -0
  72. package/dist/random.d.ts +25 -0
  73. package/dist/random.d.ts.map +1 -0
  74. package/dist/random.js +35 -0
  75. package/dist/random_alea.d.ts +23 -0
  76. package/dist/random_alea.d.ts.map +1 -0
  77. package/dist/random_alea.js +95 -0
  78. package/dist/regexp.d.ts +12 -0
  79. package/dist/regexp.d.ts.map +1 -0
  80. package/dist/regexp.js +16 -0
  81. package/dist/result.d.ts +64 -0
  82. package/dist/result.d.ts.map +1 -0
  83. package/dist/result.js +48 -0
  84. package/dist/source_json.d.ts +375 -0
  85. package/dist/source_json.d.ts.map +1 -0
  86. package/dist/source_json.js +189 -0
  87. package/dist/string.d.ts +51 -0
  88. package/dist/string.d.ts.map +1 -0
  89. package/dist/string.js +92 -0
  90. package/dist/throttle.d.ts +26 -0
  91. package/dist/throttle.d.ts.map +1 -0
  92. package/dist/throttle.js +53 -0
  93. package/dist/timings.d.ts +33 -0
  94. package/dist/timings.d.ts.map +1 -0
  95. package/dist/timings.js +75 -0
  96. package/dist/types.d.ts +77 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +10 -0
  99. package/dist/url.d.ts +10 -0
  100. package/dist/url.d.ts.map +1 -0
  101. package/dist/url.js +8 -0
  102. package/package.json +125 -0
  103. package/src/lib/array.ts +30 -0
  104. package/src/lib/async.ts +182 -0
  105. package/src/lib/colors.ts +132 -0
  106. package/src/lib/counter.ts +11 -0
  107. package/src/lib/deep_equal.ts +155 -0
  108. package/src/lib/dom.ts +108 -0
  109. package/src/lib/error.ts +22 -0
  110. package/src/lib/fetch.ts +231 -0
  111. package/src/lib/fs.ts +128 -0
  112. package/src/lib/function.ts +32 -0
  113. package/src/lib/git.ts +390 -0
  114. package/src/lib/id.ts +30 -0
  115. package/src/lib/iterator.ts +8 -0
  116. package/src/lib/json.ts +61 -0
  117. package/src/lib/library_json.ts +122 -0
  118. package/src/lib/log.ts +469 -0
  119. package/src/lib/map.ts +18 -0
  120. package/src/lib/maths.ts +91 -0
  121. package/src/lib/object.ts +110 -0
  122. package/src/lib/package_json.ts +135 -0
  123. package/src/lib/path.ts +137 -0
  124. package/src/lib/print.ts +111 -0
  125. package/src/lib/process.ts +207 -0
  126. package/src/lib/random.ts +48 -0
  127. package/src/lib/random_alea.ts +107 -0
  128. package/src/lib/regexp.ts +17 -0
  129. package/src/lib/result.ts +67 -0
  130. package/src/lib/source_json.ts +209 -0
  131. package/src/lib/string.ts +99 -0
  132. package/src/lib/throttle.ts +70 -0
  133. package/src/lib/timings.ts +93 -0
  134. package/src/lib/types.ts +99 -0
  135. package/src/lib/url.ts +14 -0
package/dist/object.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Returns a boolean indicating if `value` is
3
+ * a plain object, possibly created with `Object.create(null)`.
4
+ * But warning! This fails for some obscure corner cases, use a proper library for weird things.
5
+ */
6
+ export const is_plain_object = (value) => value ? value.constructor === Object || value.constructor === undefined : false;
7
+ /**
8
+ * Iterated keys in `for..in` are always returned as strings,
9
+ * so to prevent usage errors the key type of `mapper` is always a string.
10
+ * Symbols are not enumerable as keys, so they're excluded.
11
+ */
12
+ export const map_record = (obj, mapper) => {
13
+ const result = {};
14
+ for (const key in obj) {
15
+ result[key] = mapper(obj[key], key);
16
+ }
17
+ return result;
18
+ };
19
+ /**
20
+ * Creates a new object without the specified `keys`.
21
+ */
22
+ export const omit = (obj, keys) => {
23
+ const result = {};
24
+ for (const key in obj) {
25
+ if (!keys.includes(key)) {
26
+ result[key] = obj[key];
27
+ }
28
+ }
29
+ return result;
30
+ };
31
+ /**
32
+ * Creates a new object with properties that pass the `should_pick` predicate.
33
+ */
34
+ export const pick_by = (obj, should_pick) => {
35
+ const result = {};
36
+ for (const key in obj) {
37
+ const value = obj[key];
38
+ if (should_pick(value, key)) {
39
+ result[key] = value;
40
+ }
41
+ }
42
+ return result;
43
+ };
44
+ /**
45
+ * `omit_undefined` is a commonly used form of `pick_by`.
46
+ * See this issue for why it's used so much:
47
+ * https://github.com/Microsoft/TypeScript/issues/13195
48
+ * @param obj
49
+ * @returns `obj` with all `undefined` properties removed
50
+ */
51
+ export const omit_undefined = (obj) => pick_by(obj, (v) => v !== undefined);
52
+ /**
53
+ * A more explicit form of `{put_this_first: obj.put_this_first, ...obj}`.
54
+ */
55
+ export const reorder = (obj, keys) => {
56
+ const result = {};
57
+ for (const k of keys)
58
+ result[k] = obj[k];
59
+ // overwriting is probably faster than using
60
+ // a `Set` to track what's already been added
61
+ for (const k in obj)
62
+ result[k] = obj[k];
63
+ return result;
64
+ };
65
+ /**
66
+ * Frozen empty object with no properties, good for options default values.
67
+ */
68
+ export const EMPTY_OBJECT = Object.freeze({}); // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
69
+ /**
70
+ * Performs a depth-first traversal of an object's enumerable properties,
71
+ * calling `cb` for every key and value with the current `obj` context.
72
+ * @param obj - any object with enumerable properties
73
+ * @param cb - receives the key, value, and `obj` for every enumerable property on `obj` and its descendents
74
+ */
75
+ export const traverse = (obj, cb) => {
76
+ if (!obj || typeof obj !== 'object')
77
+ return;
78
+ for (const k in obj) {
79
+ const v = obj[k];
80
+ cb(k, v, obj);
81
+ traverse(v, cb);
82
+ }
83
+ };
84
+ export const transform_empty_object_to_undefined = (obj) => {
85
+ if (obj && Object.keys(obj).length === 0) {
86
+ return;
87
+ }
88
+ return obj;
89
+ };
@@ -0,0 +1,90 @@
1
+ import { z } from 'zod';
2
+ export declare const PackageJsonRepository: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
3
+ type: z.ZodString;
4
+ url: z.ZodURL;
5
+ directory: z.ZodOptional<z.ZodString>;
6
+ }, z.core.$loose>]>;
7
+ export type PackageJsonRepository = z.infer<typeof PackageJsonRepository>;
8
+ export declare const PackageJsonAuthor: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
9
+ name: z.ZodString;
10
+ email: z.ZodOptional<z.ZodEmail>;
11
+ url: z.ZodOptional<z.ZodURL>;
12
+ }, z.core.$loose>]>;
13
+ export type PackageJsonAuthor = z.infer<typeof PackageJsonAuthor>;
14
+ export declare const PackageJsonFunding: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
15
+ type: z.ZodString;
16
+ url: z.ZodURL;
17
+ }, z.core.$loose>]>;
18
+ export type PackageJsonFunding = z.infer<typeof PackageJsonFunding>;
19
+ export declare const ExportValue: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
20
+ export type ExportValue = z.infer<typeof ExportValue>;
21
+ /**
22
+ * Package exports can be:
23
+ * 1. A string (shorthand for main export)
24
+ * 2. null (to block exports)
25
+ * 3. A record of export conditions/paths
26
+ */
27
+ export declare const PackageJsonExports: z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>]>;
28
+ export type PackageJsonExports = z.infer<typeof PackageJsonExports>;
29
+ /**
30
+ * @see https://docs.npmjs.com/cli/v10/configuring-npm/package-json
31
+ */
32
+ export declare const PackageJson: z.ZodObject<{
33
+ name: z.ZodString;
34
+ version: z.ZodString;
35
+ private: z.ZodOptional<z.ZodBoolean>;
36
+ public: z.ZodOptional<z.ZodBoolean>;
37
+ description: z.ZodOptional<z.ZodString>;
38
+ motto: z.ZodOptional<z.ZodString>;
39
+ glyph: z.ZodOptional<z.ZodString>;
40
+ logo: z.ZodOptional<z.ZodString>;
41
+ logo_alt: z.ZodOptional<z.ZodString>;
42
+ license: z.ZodOptional<z.ZodString>;
43
+ scripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
44
+ homepage: z.ZodOptional<z.ZodURL>;
45
+ author: z.ZodUnion<readonly [z.ZodString, z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
46
+ name: z.ZodString;
47
+ email: z.ZodOptional<z.ZodEmail>;
48
+ url: z.ZodOptional<z.ZodURL>;
49
+ }, z.core.$loose>]>>]>;
50
+ repository: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodURL, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
51
+ type: z.ZodString;
52
+ url: z.ZodURL;
53
+ directory: z.ZodOptional<z.ZodString>;
54
+ }, z.core.$loose>]>]>>;
55
+ contributors: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
56
+ name: z.ZodString;
57
+ email: z.ZodOptional<z.ZodEmail>;
58
+ url: z.ZodOptional<z.ZodURL>;
59
+ }, z.core.$loose>]>]>>>;
60
+ bugs: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
61
+ url: z.ZodOptional<z.ZodURL>;
62
+ email: z.ZodOptional<z.ZodEmail>;
63
+ }, z.core.$loose>]>>;
64
+ funding: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
65
+ type: z.ZodString;
66
+ url: z.ZodURL;
67
+ }, z.core.$loose>]>, z.ZodArray<z.ZodUnion<readonly [z.ZodURL, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
68
+ type: z.ZodString;
69
+ url: z.ZodURL;
70
+ }, z.core.$loose>]>]>>]>>;
71
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
72
+ type: z.ZodOptional<z.ZodString>;
73
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
74
+ os: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ cpu: z.ZodOptional<z.ZodArray<z.ZodString>>;
76
+ dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
77
+ devDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
78
+ peerDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
79
+ peerDependenciesMeta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
80
+ optional: z.ZodBoolean;
81
+ }, z.core.$loose>>>;
82
+ optionalDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
83
+ bin: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
84
+ sideEffects: z.ZodOptional<z.ZodArray<z.ZodString>>;
85
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
86
+ main: z.ZodOptional<z.ZodString>;
87
+ exports: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>]>, z.ZodTransform<string | Record<string, unknown> | null | undefined, string | Record<string, unknown> | null>>>;
88
+ }, z.core.$loose>;
89
+ export type PackageJson = z.infer<typeof PackageJson>;
90
+ //# sourceMappingURL=package_json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/package_json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAMtB,eAAO,MAAM,qBAAqB;;;;mBAOhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,eAAO,MAAM,iBAAiB;;;;mBAO5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB;;;mBAM7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAapE,eAAO,MAAM,WAAW,yEAAsB,CAAC;AAC/C,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,kJAI7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoEtB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { z } from 'zod';
2
+ import { count_graphemes } from './string.js';
3
+ import { transform_empty_object_to_undefined } from './object.js';
4
+ import { Url } from './url.js';
5
+ export const PackageJsonRepository = z.union([
6
+ z.string(),
7
+ z.looseObject({
8
+ type: z.string(),
9
+ url: Url,
10
+ directory: z.string().optional(),
11
+ }),
12
+ ]);
13
+ export const PackageJsonAuthor = z.union([
14
+ z.string(),
15
+ z.looseObject({
16
+ name: z.string(),
17
+ email: z.email().optional(),
18
+ url: Url.optional(),
19
+ }),
20
+ ]);
21
+ export const PackageJsonFunding = z.union([
22
+ z.string(),
23
+ z.looseObject({
24
+ type: z.string(),
25
+ url: Url,
26
+ }),
27
+ ]);
28
+ // The base export value schema that can be a string, null, or nested conditions
29
+ const export_value_schema = z.lazy(() => z.union([
30
+ z.string(),
31
+ z.null(),
32
+ z.record(z.string(), z.lazy(() => export_value_schema)),
33
+ ]));
34
+ export const ExportValue = export_value_schema;
35
+ /**
36
+ * Package exports can be:
37
+ * 1. A string (shorthand for main export)
38
+ * 2. null (to block exports)
39
+ * 3. A record of export conditions/paths
40
+ */
41
+ export const PackageJsonExports = z.union([
42
+ z.string(),
43
+ z.null(),
44
+ z.record(z.string(), export_value_schema),
45
+ ]);
46
+ /**
47
+ * @see https://docs.npmjs.com/cli/v10/configuring-npm/package-json
48
+ */
49
+ export const PackageJson = z.looseObject({
50
+ // according to the npm docs, `name` and `version` are the only required properties
51
+ name: z.string(),
52
+ version: z.string(),
53
+ private: z
54
+ .boolean()
55
+ .meta({ description: 'disallow publishing to the configured registry' })
56
+ .optional(),
57
+ public: z
58
+ .boolean()
59
+ .meta({
60
+ description: 'a Gro extension that enables publishing `.well-known/package.json` and `.well-known/src`',
61
+ })
62
+ .optional(),
63
+ description: z.string().optional(),
64
+ motto: z
65
+ .string()
66
+ .meta({ description: "a Gro extension that's a short phrase that represents this project" })
67
+ .optional(),
68
+ glyph: z
69
+ .string()
70
+ .meta({
71
+ description: "a Gro extension that's a single unicode character that represents this project",
72
+ })
73
+ .refine((v) => count_graphemes(v) === 1, 'must be a single unicode character')
74
+ .optional(),
75
+ logo: z
76
+ .string()
77
+ .meta({
78
+ description: "a Gro extension that's a link relative to the `homepage` to an image that represents this project",
79
+ })
80
+ .optional(),
81
+ logo_alt: z
82
+ .string()
83
+ .meta({ description: "a Gro extension that's the alt text for the `logo`" })
84
+ .optional(),
85
+ license: z.string().optional(),
86
+ scripts: z.record(z.string(), z.string()).optional(),
87
+ homepage: Url.optional(),
88
+ author: z.union([z.string(), PackageJsonAuthor.optional()]),
89
+ repository: z.union([z.string(), Url, PackageJsonRepository]).optional(),
90
+ contributors: z.array(z.union([z.string(), PackageJsonAuthor])).optional(),
91
+ bugs: z
92
+ .union([z.string(), z.looseObject({ url: Url.optional(), email: z.email().optional() })])
93
+ .optional(),
94
+ funding: z
95
+ .union([Url, PackageJsonFunding, z.array(z.union([Url, PackageJsonFunding]))])
96
+ .optional(),
97
+ keywords: z.array(z.string()).optional(),
98
+ type: z.string().optional(),
99
+ engines: z.record(z.string(), z.string()).optional(),
100
+ os: z.array(z.string()).optional(),
101
+ cpu: z.array(z.string()).optional(),
102
+ dependencies: z.record(z.string(), z.string()).optional(),
103
+ devDependencies: z.record(z.string(), z.string()).optional(),
104
+ peerDependencies: z.record(z.string(), z.string()).optional(),
105
+ peerDependenciesMeta: z.record(z.string(), z.looseObject({ optional: z.boolean() })).optional(),
106
+ optionalDependencies: z.record(z.string(), z.string()).optional(),
107
+ bin: z.record(z.string(), z.string()).optional(),
108
+ sideEffects: z.array(z.string()).optional(),
109
+ files: z.array(z.string()).optional(),
110
+ main: z.string().optional(),
111
+ exports: PackageJsonExports.transform(transform_empty_object_to_undefined).optional(),
112
+ });
package/dist/path.d.ts ADDED
@@ -0,0 +1,63 @@
1
+ import type { Flavored } from './types.js';
2
+ /**
3
+ * An absolute path on the filesystem. Named "id" to be consistent with Rollup.
4
+ */
5
+ export type PathId = Flavored<string, 'PathId'>;
6
+ /**
7
+ * Basic information about a filesystem path.
8
+ */
9
+ export interface PathInfo {
10
+ id: PathId;
11
+ is_directory: boolean;
12
+ }
13
+ /**
14
+ * A resolved path with both the original path string and its absolute id.
15
+ */
16
+ export interface ResolvedPath extends PathInfo {
17
+ path: string;
18
+ }
19
+ /**
20
+ * A filter function for paths, can distinguish between files and directories.
21
+ */
22
+ export type PathFilter = (path: string, is_directory: boolean) => boolean;
23
+ /**
24
+ * A filter function for file paths only.
25
+ */
26
+ export type FileFilter = (path: string) => boolean;
27
+ /**
28
+ * Converts a URL to a file path string, or returns the string as-is.
29
+ */
30
+ export declare const to_file_path: (path_or_url: string | URL) => string;
31
+ /**
32
+ * @example parse_path_parts('./foo/bar/baz.ts') => ['foo', 'foo/bar', 'foo/bar/baz.ts']
33
+ */
34
+ export declare const parse_path_parts: (path: string) => Array<string>;
35
+ /**
36
+ * Gets the individual parts of a path, ignoring dots and separators.
37
+ * @example parse_path_segments('/foo/bar/baz.ts') => ['foo', 'bar', 'baz.ts']
38
+ */
39
+ export declare const parse_path_segments: (path: string) => Array<string>;
40
+ /**
41
+ * A piece of a parsed path, either a path segment or separator.
42
+ */
43
+ export type PathPiece = {
44
+ type: 'piece';
45
+ path: PathId;
46
+ name: string;
47
+ } | {
48
+ type: 'separator';
49
+ path: PathId;
50
+ };
51
+ /**
52
+ * Treats all paths as absolute, so the first piece is always a `'/'` with type `'separator'`.
53
+ * @todo maybe rethink this API, it's a bit weird, but fits the usage in `ui/Breadcrumbs.svelte`
54
+ */
55
+ export declare const parse_path_pieces: (raw_path: string) => Array<PathPiece>;
56
+ /**
57
+ * Converts a string into a URL-compatible slug.
58
+ * @param str the string to convert
59
+ * @param map_special_characters if `true`, characters like `ñ` are converted to their ASCII equivalents, runs around 5x faster when disabled
60
+ * @mutates special_char_mappers calls `get_special_char_mappers()` which lazily initializes the module-level array if `map_special_characters` is true
61
+ */
62
+ export declare const slugify: (str: string, map_special_characters?: boolean) => string;
63
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC7C,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,KAAK,OAAO,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,GAAG,GAAG,KAAG,MACgC,CAAC;AAE1F;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,KAAK,CAAC,MAAM,CAU3D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,KAAK,CAAC,MAAM,CACH,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,SAAS,GAClB;IACA,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACZ,GACD;IACA,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACZ,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,KAAG,KAAK,CAAC,SAAS,CAgBnE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,gCAA6B,KAAG,MAYpE,CAAC"}
package/dist/path.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Converts a URL to a file path string, or returns the string as-is.
3
+ */
4
+ export const to_file_path = (path_or_url) => typeof path_or_url === 'string' ? path_or_url : decodeURIComponent(path_or_url.pathname);
5
+ /**
6
+ * @example parse_path_parts('./foo/bar/baz.ts') => ['foo', 'foo/bar', 'foo/bar/baz.ts']
7
+ */
8
+ export const parse_path_parts = (path) => {
9
+ const segments = parse_path_segments(path);
10
+ let current_path = path.startsWith('/') ? '/' : '';
11
+ return segments.map((segment) => {
12
+ if (current_path && current_path !== '/') {
13
+ current_path += '/';
14
+ }
15
+ current_path += segment;
16
+ return current_path;
17
+ });
18
+ };
19
+ /**
20
+ * Gets the individual parts of a path, ignoring dots and separators.
21
+ * @example parse_path_segments('/foo/bar/baz.ts') => ['foo', 'bar', 'baz.ts']
22
+ */
23
+ export const parse_path_segments = (path) => path.split('/').filter((s) => s && s !== '.' && s !== '..');
24
+ /**
25
+ * Treats all paths as absolute, so the first piece is always a `'/'` with type `'separator'`.
26
+ * @todo maybe rethink this API, it's a bit weird, but fits the usage in `ui/Breadcrumbs.svelte`
27
+ */
28
+ export const parse_path_pieces = (raw_path) => {
29
+ const pieces = [];
30
+ const path_segments = parse_path_segments(raw_path);
31
+ if (path_segments.length) {
32
+ pieces.push({ type: 'separator', path: '/' });
33
+ }
34
+ let path = '';
35
+ for (let i = 0; i < path_segments.length; i++) {
36
+ const path_segment = path_segments[i];
37
+ path += '/' + path_segment;
38
+ pieces.push({ type: 'piece', name: path_segment, path });
39
+ if (i !== path_segments.length - 1) {
40
+ pieces.push({ type: 'separator', path });
41
+ }
42
+ }
43
+ return pieces;
44
+ };
45
+ /**
46
+ * Converts a string into a URL-compatible slug.
47
+ * @param str the string to convert
48
+ * @param map_special_characters if `true`, characters like `ñ` are converted to their ASCII equivalents, runs around 5x faster when disabled
49
+ * @mutates special_char_mappers calls `get_special_char_mappers()` which lazily initializes the module-level array if `map_special_characters` is true
50
+ */
51
+ export const slugify = (str, map_special_characters = true) => {
52
+ let s = str.toLowerCase();
53
+ if (map_special_characters) {
54
+ for (const mapper of get_special_char_mappers()) {
55
+ s = mapper(s);
56
+ }
57
+ }
58
+ return s
59
+ .replace(/[^\s\w-]/g, '')
60
+ .split(/[\s-]+/g) // collapse whitespace
61
+ .filter(Boolean)
62
+ .join('-'); // remove all `''`
63
+ };
64
+ /**
65
+ * @see https://stackoverflow.com/questions/1053902/how-to-convert-a-title-to-a-url-slug-in-jquery/5782563#5782563
66
+ */
67
+ const special_char_from = 'áäâàãåÆþčçćďđéěëèêẽĕȇğíìîïıňñóöòôõøðřŕšşßťúůüùûýÿž';
68
+ const special_char_to = 'aaaaaaabcccddeeeeeeeegiiiiinnooooooorrssstuuuuuyyz';
69
+ let special_char_mappers;
70
+ /**
71
+ * Lazily constructs `special_char_mappers` which
72
+ * converts special characters to their ASCII equivalents.
73
+ * @mutates special_char_mappers pushes mapper functions into module-level array on first call
74
+ */
75
+ const get_special_char_mappers = () => {
76
+ if (special_char_mappers)
77
+ return special_char_mappers;
78
+ special_char_mappers = [];
79
+ for (let i = 0, j = special_char_from.length; i < j; i++) {
80
+ special_char_mappers.push((s) => s.replaceAll(special_char_from.charAt(i), special_char_to.charAt(i)));
81
+ }
82
+ return special_char_mappers;
83
+ };
@@ -0,0 +1,52 @@
1
+ import type { styleText } from 'node:util';
2
+ import type { Timings } from './timings.js';
3
+ import type { Logger } from './log.js';
4
+ export declare let st: typeof styleText;
5
+ /**
6
+ * Configures the module-level styling function for colored output.
7
+ * @mutates st assigns the module-level `st` variable
8
+ */
9
+ export declare const configure_print_colors: (s: typeof styleText | null | undefined) => typeof styleText;
10
+ /**
11
+ * Formats a key-value pair for printing.
12
+ */
13
+ export declare const print_key_value: (key: string, value: string | number) => string;
14
+ /**
15
+ * Formats a `number` of milliseconds for printing.
16
+ */
17
+ export declare const print_ms: (ms: number, decimals?: number, separator?: string) => string;
18
+ /**
19
+ * Formats a `number` with separators for improved readability.
20
+ */
21
+ export declare const print_number_with_separators: (v: string, separator?: string) => string;
22
+ /**
23
+ * Formats a `string` for printing.
24
+ */
25
+ export declare const print_string: (value: string) => string;
26
+ /**
27
+ * Formats a `number` for printing.
28
+ */
29
+ export declare const print_number: (value: number) => string;
30
+ /**
31
+ * Formats a `boolean` for printing.
32
+ */
33
+ export declare const print_boolean: (value: boolean) => string;
34
+ /**
35
+ * Formats any value for printing.
36
+ */
37
+ export declare const print_value: (value: unknown) => string;
38
+ /**
39
+ * Formats an error for printing.
40
+ * Because throwing errors and rejecting promises isn't typesafe,
41
+ * don't assume the arg is an `Error` and try to return something useful.
42
+ */
43
+ export declare const print_error: (err: Error) => string;
44
+ /**
45
+ * Formats a timing entry with `key` for printing.
46
+ */
47
+ export declare const print_timing: (key: string | number, timing: number | undefined) => string;
48
+ /**
49
+ * Prints all timings in a `Timings` object.
50
+ */
51
+ export declare const print_timings: (timings: Timings, log: Logger) => void;
52
+ //# sourceMappingURL=print.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/print.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAErC,eAAO,IAAI,EAAE,EAAE,OAAO,SAAuB,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAClC,GAAG,OAAO,SAAS,GAAG,IAAI,GAAG,SAAS,KACpC,OAAO,SAGT,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,GAAG,MAAM,KAAG,MACtB,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,IAAI,MAAM,EAAE,WAAW,MAAM,EAAE,YAAY,MAAM,KAAG,MAI5E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAAI,GAAG,MAAM,EAAE,kBAAe,KAAG,MAYzE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAAmC,CAAC;AAEjF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAAgC,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,MAAkC,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,KAAG,MAgB5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,KAAK,KAAG,MAIvC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,GAAG,MAAM,EAAE,QAAQ,MAAM,GAAG,SAAS,KAAG,MAC2B,CAAC;AAE5G;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO,EAAE,KAAK,MAAM,KAAG,IAI7D,CAAC"}
package/dist/print.js ADDED
@@ -0,0 +1,89 @@
1
+ export let st = (_, v) => v;
2
+ /**
3
+ * Configures the module-level styling function for colored output.
4
+ * @mutates st assigns the module-level `st` variable
5
+ */
6
+ export const configure_print_colors = (s) => {
7
+ st = s ?? ((_, v) => v);
8
+ return st;
9
+ };
10
+ /**
11
+ * Formats a key-value pair for printing.
12
+ */
13
+ export const print_key_value = (key, value) => st('gray', `${key}(`) + value + st('gray', ')');
14
+ /**
15
+ * Formats a `number` of milliseconds for printing.
16
+ */
17
+ export const print_ms = (ms, decimals, separator) => {
18
+ const decimal_count = decimals ?? (ms >= 10 ? 0 : ms < 0.1 ? 2 : 1);
19
+ const rounded = ms.toFixed(decimal_count);
20
+ return st('white', print_number_with_separators(rounded, separator)) + st('gray', 'ms');
21
+ };
22
+ /**
23
+ * Formats a `number` with separators for improved readability.
24
+ */
25
+ export const print_number_with_separators = (v, separator = ',') => {
26
+ if (!separator)
27
+ return v;
28
+ const decimal_index = v.indexOf('.');
29
+ const start_index = (decimal_index === -1 ? v.length : decimal_index) - 1;
30
+ let s = decimal_index === -1 ? '' : v.slice(start_index + 1);
31
+ let count = 0;
32
+ for (let i = start_index; i >= 0; i--) {
33
+ count++;
34
+ if (count > 3 && count % 3 === 1)
35
+ s = separator + s;
36
+ s = v[i] + s;
37
+ }
38
+ return s;
39
+ };
40
+ /**
41
+ * Formats a `string` for printing.
42
+ */
43
+ export const print_string = (value) => st('green', `'${value}'`);
44
+ /**
45
+ * Formats a `number` for printing.
46
+ */
47
+ export const print_number = (value) => st('cyan', value + '');
48
+ /**
49
+ * Formats a `boolean` for printing.
50
+ */
51
+ export const print_boolean = (value) => st('yellow', value + '');
52
+ /**
53
+ * Formats any value for printing.
54
+ */
55
+ export const print_value = (value) => {
56
+ if (Array.isArray(value)) {
57
+ return st('blue', '[') + value.map(print_value).join(st('blue', ', ')) + st('blue', ']');
58
+ }
59
+ switch (typeof value) {
60
+ case 'string':
61
+ return print_string(value);
62
+ case 'number':
63
+ return print_number(value);
64
+ case 'boolean':
65
+ return print_boolean(value);
66
+ case 'object':
67
+ return value === null ? st('blue', 'null') : st('magenta', JSON.stringify(value));
68
+ default:
69
+ return st('blue', value + '');
70
+ }
71
+ };
72
+ /**
73
+ * Formats an error for printing.
74
+ * Because throwing errors and rejecting promises isn't typesafe,
75
+ * don't assume the arg is an `Error` and try to return something useful.
76
+ */
77
+ export const print_error = (err) => st('yellow', err.stack ?? ((err.message && `Error: ${err.message}`) || `Unknown error: ${err}`));
78
+ /**
79
+ * Formats a timing entry with `key` for printing.
80
+ */
81
+ export const print_timing = (key, timing) => `${timing === undefined ? '...' : print_ms(timing, undefined)} ${st('gray', '←')} ${st('gray', key + '')}`;
82
+ /**
83
+ * Prints all timings in a `Timings` object.
84
+ */
85
+ export const print_timings = (timings, log) => {
86
+ for (const [key, timing] of timings.entries()) {
87
+ log.debug(print_timing(key, timing));
88
+ }
89
+ };
@@ -0,0 +1,77 @@
1
+ import { type SpawnOptions, type ChildProcess } from 'node:child_process';
2
+ import type { Result } from './result.js';
3
+ export interface SpawnedProcess {
4
+ child: ChildProcess;
5
+ closed: Promise<SpawnResult>;
6
+ }
7
+ export interface Spawned {
8
+ child: ChildProcess;
9
+ signal: NodeJS.Signals | null;
10
+ code: number | null;
11
+ }
12
+ export type SpawnResult = Result<Spawned, Spawned>;
13
+ /**
14
+ * A convenient promise wrapper around `spawn_process`
15
+ * intended for commands that have an end, not long running-processes like watchers.
16
+ * Any more advanced usage should use `spawn_process` directly for access to the `child` process.
17
+ */
18
+ export declare const spawn: (...args: Parameters<typeof spawn_process>) => Promise<SpawnResult>;
19
+ export interface SpawnedOut {
20
+ result: SpawnResult;
21
+ stdout: string | null;
22
+ stderr: string | null;
23
+ }
24
+ /**
25
+ * Similar to `spawn` but buffers and returns `stdout` and `stderr` as strings.
26
+ */
27
+ export declare const spawn_out: (command: string, args?: ReadonlyArray<string>, options?: SpawnOptions) => Promise<SpawnedOut>;
28
+ /**
29
+ * Wraps the normal Node `childProcess.spawn` with graceful child shutdown behavior.
30
+ * Also returns a convenient `closed` promise.
31
+ * If you only need `closed`, prefer the shorthand function `spawn`.
32
+ * @mutates global_spawn calls `register_global_spawn()` which adds to the module-level Set
33
+ */
34
+ export declare const spawn_process: (command: string, args?: ReadonlyArray<string>, options?: SpawnOptions) => SpawnedProcess;
35
+ export declare const print_child_process: (child: ChildProcess) => string;
36
+ /**
37
+ * We register spawned processes gloabally so we can gracefully exit child processes.
38
+ * Otherwise, errors can cause zombie processes, sometimes blocking ports even!
39
+ */
40
+ export declare const global_spawn: Set<ChildProcess>;
41
+ /**
42
+ * Returns a function that unregisters the `child`.
43
+ * @param child the child process to register
44
+ * @returns cleanup function that removes the child from `global_spawn`
45
+ * @mutates global_spawn adds child to the module-level Set, and the returned function removes it
46
+ */
47
+ export declare const register_global_spawn: (child: ChildProcess) => (() => void);
48
+ /**
49
+ * Kills a child process and returns a `SpawnResult`.
50
+ */
51
+ export declare const despawn: (child: ChildProcess) => Promise<SpawnResult>;
52
+ /**
53
+ * Kills all globally registered child processes.
54
+ * @mutates global_spawn indirectly removes processes through `despawn()` calls
55
+ */
56
+ export declare const despawn_all: () => Promise<Array<SpawnResult>>;
57
+ /**
58
+ * Attaches the `'uncoughtException'` event to despawn all processes,
59
+ * and enables custom error logging with `to_error_label`.
60
+ * @param to_error_label - Customize the error label or return `null` for the default `origin`.
61
+ * @param map_error_text - Customize the error text. Return `''` to silence, or `null` for the default `print_error(err)`.
62
+ */
63
+ export declare const attach_process_error_handlers: (to_error_label?: (err: Error, origin: NodeJS.UncaughtExceptionOrigin) => string | null, map_error_text?: (err: Error, origin: NodeJS.UncaughtExceptionOrigin) => string | null, handle_error?: (err: Error, origin: NodeJS.UncaughtExceptionOrigin) => void) => void;
64
+ /**
65
+ * Formats a `SpawnResult` for printing.
66
+ */
67
+ export declare const print_spawn_result: (result: SpawnResult) => string;
68
+ export interface RestartableProcess {
69
+ restart: () => void;
70
+ kill: () => Promise<void>;
71
+ }
72
+ /**
73
+ * Like `spawn_process` but with `restart` and `kill`,
74
+ * handling many concurrent `restart` calls gracefully.
75
+ */
76
+ export declare const spawn_restartable_process: (command: string, args?: ReadonlyArray<string>, options?: SpawnOptions) => RestartableProcess;
77
+ //# sourceMappingURL=process.d.ts.map