@scalar/helpers 0.4.1 → 0.4.2

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 (111) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/array/add-to-map-array.js +7 -8
  3. package/dist/array/is-defined.js +12 -5
  4. package/dist/array/sort-by-order.js +60 -18
  5. package/dist/consts/content-types.js +13 -14
  6. package/dist/dom/freeze-element.js +56 -42
  7. package/dist/dom/scroll-to-id.js +33 -27
  8. package/dist/file/json2xml.js +79 -61
  9. package/dist/general/create-limiter.js +47 -31
  10. package/dist/general/debounce.js +86 -66
  11. package/dist/general/extract-config-secrets.js +29 -27
  12. package/dist/general/has-modifier.js +9 -8
  13. package/dist/general/is-mac-os.js +23 -21
  14. package/dist/http/can-method-have-body.js +4 -6
  15. package/dist/http/http-info.js +63 -61
  16. package/dist/http/http-methods.js +4 -7
  17. package/dist/http/http-status-codes.js +316 -320
  18. package/dist/http/is-http-method.js +3 -6
  19. package/dist/http/normalize-http-method.js +19 -19
  20. package/dist/json/escape-json-pointer.js +6 -5
  21. package/dist/json/parse-json-pointer-segments.js +11 -6
  22. package/dist/json/pretty-print-json.d.ts +9 -0
  23. package/dist/json/pretty-print-json.d.ts.map +1 -0
  24. package/dist/json/pretty-print-json.js +42 -0
  25. package/dist/json/unescape-json-pointer.js +7 -5
  26. package/dist/node/path.js +168 -138
  27. package/dist/object/get-value-at-path.js +17 -11
  28. package/dist/object/is-object.js +24 -10
  29. package/dist/object/local-storage.js +50 -42
  30. package/dist/object/object-entries.js +2 -5
  31. package/dist/object/object-keys.js +5 -5
  32. package/dist/object/object-replace.js +13 -12
  33. package/dist/object/omit-undefined-values.js +18 -18
  34. package/dist/object/prevent-pollution.js +27 -10
  35. package/dist/object/to-json-compatible.js +71 -62
  36. package/dist/queue/queue.js +103 -84
  37. package/dist/regex/find-variables.js +13 -8
  38. package/dist/regex/regex-helpers.js +17 -17
  39. package/dist/regex/replace-variables.js +21 -19
  40. package/dist/string/camel-to-title.js +10 -5
  41. package/dist/string/capitalize.js +5 -5
  42. package/dist/string/create-hash.js +19 -16
  43. package/dist/string/generate-hash.js +153 -127
  44. package/dist/string/iterate-title.js +13 -11
  45. package/dist/string/truncate.js +16 -9
  46. package/dist/testing/console-spies.js +19 -24
  47. package/dist/testing/measure.js +42 -19
  48. package/dist/testing/measure.test-d.js +12 -9
  49. package/dist/testing/sleep.js +5 -5
  50. package/dist/url/ensure-protocol.js +8 -10
  51. package/dist/url/extract-server-from-path.js +53 -28
  52. package/dist/url/is-local-url.js +24 -18
  53. package/dist/url/is-relative-path.js +15 -13
  54. package/dist/url/is-valid-url.js +17 -10
  55. package/dist/url/make-url-absolute.js +39 -28
  56. package/dist/url/merge-urls.js +74 -52
  57. package/dist/url/redirect-to-proxy.js +68 -39
  58. package/package.json +5 -9
  59. package/dist/array/add-to-map-array.js.map +0 -7
  60. package/dist/array/is-defined.js.map +0 -7
  61. package/dist/array/sort-by-order.js.map +0 -7
  62. package/dist/consts/content-types.js.map +0 -7
  63. package/dist/dom/freeze-element.js.map +0 -7
  64. package/dist/dom/scroll-to-id.js.map +0 -7
  65. package/dist/file/json2xml.js.map +0 -7
  66. package/dist/general/create-limiter.js.map +0 -7
  67. package/dist/general/debounce.js.map +0 -7
  68. package/dist/general/extract-config-secrets.js.map +0 -7
  69. package/dist/general/has-modifier.js.map +0 -7
  70. package/dist/general/is-mac-os.js.map +0 -7
  71. package/dist/http/can-method-have-body.js.map +0 -7
  72. package/dist/http/http-info.js.map +0 -7
  73. package/dist/http/http-methods.js.map +0 -7
  74. package/dist/http/http-status-codes.js.map +0 -7
  75. package/dist/http/is-http-method.js.map +0 -7
  76. package/dist/http/normalize-http-method.js.map +0 -7
  77. package/dist/json/escape-json-pointer.js.map +0 -7
  78. package/dist/json/parse-json-pointer-segments.js.map +0 -7
  79. package/dist/json/unescape-json-pointer.js.map +0 -7
  80. package/dist/node/path.js.map +0 -7
  81. package/dist/object/get-value-at-path.js.map +0 -7
  82. package/dist/object/is-object.js.map +0 -7
  83. package/dist/object/local-storage.js.map +0 -7
  84. package/dist/object/object-entries.js.map +0 -7
  85. package/dist/object/object-keys.js.map +0 -7
  86. package/dist/object/object-replace.js.map +0 -7
  87. package/dist/object/omit-undefined-values.js.map +0 -7
  88. package/dist/object/prevent-pollution.js.map +0 -7
  89. package/dist/object/to-json-compatible.js.map +0 -7
  90. package/dist/queue/queue.js.map +0 -7
  91. package/dist/regex/find-variables.js.map +0 -7
  92. package/dist/regex/regex-helpers.js.map +0 -7
  93. package/dist/regex/replace-variables.js.map +0 -7
  94. package/dist/string/camel-to-title.js.map +0 -7
  95. package/dist/string/capitalize.js.map +0 -7
  96. package/dist/string/create-hash.js.map +0 -7
  97. package/dist/string/generate-hash.js.map +0 -7
  98. package/dist/string/iterate-title.js.map +0 -7
  99. package/dist/string/truncate.js.map +0 -7
  100. package/dist/testing/console-spies.js.map +0 -7
  101. package/dist/testing/measure.js.map +0 -7
  102. package/dist/testing/measure.test-d.js.map +0 -7
  103. package/dist/testing/sleep.js.map +0 -7
  104. package/dist/url/ensure-protocol.js.map +0 -7
  105. package/dist/url/extract-server-from-path.js.map +0 -7
  106. package/dist/url/is-local-url.js.map +0 -7
  107. package/dist/url/is-relative-path.js.map +0 -7
  108. package/dist/url/is-valid-url.js.map +0 -7
  109. package/dist/url/make-url-absolute.js.map +0 -7
  110. package/dist/url/merge-urls.js.map +0 -7
  111. package/dist/url/redirect-to-proxy.js.map +0 -7
@@ -1,67 +1,87 @@
1
- const debounce = (options = {}) => {
2
- const { delay = 328, maxWait } = options;
3
- const timeouts = /* @__PURE__ */ new Map();
4
- const maxWaitTimeouts = /* @__PURE__ */ new Map();
5
- const latestFunctions = /* @__PURE__ */ new Map();
6
- const cleanup = () => {
7
- timeouts.forEach(clearTimeout);
8
- maxWaitTimeouts.forEach(clearTimeout);
9
- timeouts.clear();
10
- maxWaitTimeouts.clear();
11
- latestFunctions.clear();
12
- };
13
- const executeAndCleanup = (key) => {
14
- const fn = latestFunctions.get(key);
15
- const timeout = timeouts.get(key);
16
- if (timeout !== void 0) {
17
- clearTimeout(timeout);
18
- timeouts.delete(key);
19
- }
20
- const maxWaitTimeout = maxWaitTimeouts.get(key);
21
- if (maxWaitTimeout !== void 0) {
22
- clearTimeout(maxWaitTimeout);
23
- maxWaitTimeouts.delete(key);
24
- }
25
- latestFunctions.delete(key);
26
- if (fn !== void 0) {
27
- try {
28
- fn();
29
- } catch {
30
- }
31
- }
32
- };
33
- const execute = (key, fn) => {
34
- latestFunctions.set(key, fn);
35
- const existingTimeout = timeouts.get(key);
36
- if (existingTimeout !== void 0) {
37
- clearTimeout(existingTimeout);
38
- }
39
- timeouts.set(
40
- key,
41
- setTimeout(() => executeAndCleanup(key), delay)
42
- );
43
- if (maxWait !== void 0 && !maxWaitTimeouts.has(key)) {
44
- maxWaitTimeouts.set(
45
- key,
46
- setTimeout(() => executeAndCleanup(key), maxWait)
47
- );
48
- }
49
- };
50
- const flush = (key) => {
51
- if (!latestFunctions.has(key)) {
52
- return;
53
- }
54
- executeAndCleanup(key);
55
- };
56
- const flushAll = () => {
57
- const keys = [...latestFunctions.keys()];
58
- for (const key of keys) {
59
- executeAndCleanup(key);
60
- }
61
- };
62
- return { execute, cleanup, flush, flushAll };
1
+ /**
2
+ * Creates a debounced function executor that delays execution until after a specified time.
3
+ * Multiple calls with the same key will cancel previous pending executions.
4
+ *
5
+ * This is useful for batching rapid updates (like auto-save or API calls) to avoid
6
+ * unnecessary processing or network requests.
7
+ *
8
+ * @param options - Configuration options for delay, maxWait, and key separator
9
+ * @returns A function that accepts a key array and callback to execute
10
+ *
11
+ * @example
12
+ * const debouncedSave = debounce({ delay: 328 })
13
+ * debouncedSave.execute(['user', '123'], () => saveUser(user))
14
+ *
15
+ * @example
16
+ * // With maxWait to guarantee execution even with continuous calls
17
+ * const debouncedSave = debounce({ delay: 328, maxWait: 2000 })
18
+ * debouncedSave.execute(['user', '123'], () => saveUser(user))
19
+ */
20
+ export const debounce = (options = {}) => {
21
+ const { delay = 328, maxWait } = options;
22
+ const timeouts = new Map();
23
+ const maxWaitTimeouts = new Map();
24
+ const latestFunctions = new Map();
25
+ const cleanup = () => {
26
+ timeouts.forEach(clearTimeout);
27
+ maxWaitTimeouts.forEach(clearTimeout);
28
+ timeouts.clear();
29
+ maxWaitTimeouts.clear();
30
+ latestFunctions.clear();
31
+ };
32
+ /** Executes the function and cleans up all associated timeouts */
33
+ const executeAndCleanup = (key) => {
34
+ // Get the latest function for this key
35
+ const fn = latestFunctions.get(key);
36
+ // Clear both timeout types
37
+ const timeout = timeouts.get(key);
38
+ if (timeout !== undefined) {
39
+ clearTimeout(timeout);
40
+ timeouts.delete(key);
41
+ }
42
+ const maxWaitTimeout = maxWaitTimeouts.get(key);
43
+ if (maxWaitTimeout !== undefined) {
44
+ clearTimeout(maxWaitTimeout);
45
+ maxWaitTimeouts.delete(key);
46
+ }
47
+ // Clear the latest function reference
48
+ latestFunctions.delete(key);
49
+ // Execute the function if it exists
50
+ if (fn !== undefined) {
51
+ try {
52
+ fn();
53
+ }
54
+ catch {
55
+ // Errors are silently caught to prevent the debounce mechanism from breaking
56
+ }
57
+ }
58
+ };
59
+ const execute = (key, fn) => {
60
+ // Store the latest function for this key
61
+ latestFunctions.set(key, fn);
62
+ // Clear existing debounce timeout
63
+ const existingTimeout = timeouts.get(key);
64
+ if (existingTimeout !== undefined) {
65
+ clearTimeout(existingTimeout);
66
+ }
67
+ // Set debounce timeout
68
+ timeouts.set(key, setTimeout(() => executeAndCleanup(key), delay));
69
+ // Set maxWait timeout only if configured and this is a new sequence
70
+ if (maxWait !== undefined && !maxWaitTimeouts.has(key)) {
71
+ maxWaitTimeouts.set(key, setTimeout(() => executeAndCleanup(key), maxWait));
72
+ }
73
+ };
74
+ const flush = (key) => {
75
+ if (!latestFunctions.has(key)) {
76
+ return;
77
+ }
78
+ executeAndCleanup(key);
79
+ };
80
+ const flushAll = () => {
81
+ const keys = [...latestFunctions.keys()];
82
+ for (const key of keys) {
83
+ executeAndCleanup(key);
84
+ }
85
+ };
86
+ return { execute, cleanup, flush, flushAll };
63
87
  };
64
- export {
65
- debounce
66
- };
67
- //# sourceMappingURL=debounce.js.map
@@ -1,31 +1,33 @@
1
- import { objectEntries } from "../object/object-entries.js";
1
+ import { objectEntries } from '../object/object-entries.js';
2
+ /**
3
+ * Mapping of field names to their corresponding x-scalar-secret extension names.
4
+ */
2
5
  const SECRET_FIELD_MAPPINGS = {
3
- clientSecret: "x-scalar-secret-client-secret",
4
- password: "x-scalar-secret-password",
5
- token: "x-scalar-secret-token",
6
- username: "x-scalar-secret-username",
7
- value: "x-scalar-secret-token",
8
- "x-scalar-client-id": "x-scalar-secret-client-id",
9
- "x-scalar-redirect-uri": "x-scalar-secret-redirect-uri"
6
+ clientSecret: 'x-scalar-secret-client-secret',
7
+ password: 'x-scalar-secret-password',
8
+ token: 'x-scalar-secret-token',
9
+ username: 'x-scalar-secret-username',
10
+ value: 'x-scalar-secret-token',
11
+ 'x-scalar-client-id': 'x-scalar-secret-client-id',
12
+ 'x-scalar-redirect-uri': 'x-scalar-secret-redirect-uri',
10
13
  };
11
- const extractConfigSecrets = (input) => objectEntries(SECRET_FIELD_MAPPINGS).reduce((result, [field, secretField]) => {
12
- const value = input[field];
13
- if (value && typeof value === "string") {
14
- result[secretField] = value;
15
- }
16
- return result;
14
+ /**
15
+ * Extracts secret fields from the config or the old schemes
16
+ * Maps original field names to their x-scalar-secret extension equivalents.
17
+ */
18
+ export const extractConfigSecrets = (input) => objectEntries(SECRET_FIELD_MAPPINGS).reduce((result, [field, secretField]) => {
19
+ const value = input[field];
20
+ if (value && typeof value === 'string') {
21
+ result[secretField] = value;
22
+ }
23
+ return result;
17
24
  }, {});
18
- const SECRETS_SET = new Set(
19
- objectEntries(SECRET_FIELD_MAPPINGS).flatMap(([oldSecret, newSecret]) => [oldSecret, newSecret])
20
- );
21
- const removeSecretFields = (input) => objectEntries(input).reduce((result, [key, value]) => {
22
- if (!SECRETS_SET.has(key)) {
23
- result[key] = value;
24
- }
25
- return result;
25
+ /** Set of all secret fields */
26
+ const SECRETS_SET = new Set(objectEntries(SECRET_FIELD_MAPPINGS).flatMap(([oldSecret, newSecret]) => [oldSecret, newSecret]));
27
+ /** Removes all secret fields from the input object */
28
+ export const removeSecretFields = (input) => objectEntries(input).reduce((result, [key, value]) => {
29
+ if (!SECRETS_SET.has(key)) {
30
+ result[key] = value;
31
+ }
32
+ return result;
26
33
  }, {});
27
- export {
28
- extractConfigSecrets,
29
- removeSecretFields
30
- };
31
- //# sourceMappingURL=extract-config-secrets.js.map
@@ -1,9 +1,10 @@
1
- import { isMacOS } from "./is-mac-os.js";
2
- const hasModifier = (keydown) => {
3
- const modifier = isMacOS() ? "metaKey" : "ctrlKey";
4
- return keydown[modifier];
1
+ import { isMacOS } from './is-mac-os.js';
2
+ /**
3
+ * Checks for the modifier key
4
+ *
5
+ * Which is meta on macOs and ctrl on linux/windows
6
+ */
7
+ export const hasModifier = (keydown) => {
8
+ const modifier = isMacOS() ? 'metaKey' : 'ctrlKey';
9
+ return keydown[modifier];
5
10
  };
6
- export {
7
- hasModifier
8
- };
9
- //# sourceMappingURL=has-modifier.js.map
@@ -1,24 +1,26 @@
1
+ /**
2
+ * Checks whether the user is on macOS
3
+ * Uses the modern navigator.userAgentData API with a fallback to navigator.userAgent
4
+ */
1
5
  const getUserAgentDataPlatform = (nav) => {
2
- const userAgentData = Reflect.get(nav, "userAgentData");
3
- if (!userAgentData || typeof userAgentData !== "object") {
4
- return void 0;
5
- }
6
- if (!("platform" in userAgentData) || typeof userAgentData.platform !== "string") {
7
- return void 0;
8
- }
9
- return userAgentData.platform;
6
+ const userAgentData = Reflect.get(nav, 'userAgentData');
7
+ if (!userAgentData || typeof userAgentData !== 'object') {
8
+ return undefined;
9
+ }
10
+ if (!('platform' in userAgentData) || typeof userAgentData.platform !== 'string') {
11
+ return undefined;
12
+ }
13
+ return userAgentData.platform;
10
14
  };
11
- const isMacOS = () => {
12
- if (typeof navigator === "undefined") {
13
- return false;
14
- }
15
- const userAgentDataPlatform = getUserAgentDataPlatform(navigator);
16
- if (userAgentDataPlatform) {
17
- return userAgentDataPlatform.toLowerCase().includes("mac");
18
- }
19
- return /Mac/.test(navigator.userAgent);
15
+ export const isMacOS = () => {
16
+ if (typeof navigator === 'undefined') {
17
+ return false;
18
+ }
19
+ // Modern approach using navigator.userAgentData
20
+ const userAgentDataPlatform = getUserAgentDataPlatform(navigator);
21
+ if (userAgentDataPlatform) {
22
+ return userAgentDataPlatform.toLowerCase().includes('mac');
23
+ }
24
+ // Fallback to userAgent
25
+ return /Mac/.test(navigator.userAgent);
20
26
  };
21
- export {
22
- isMacOS
23
- };
24
- //# sourceMappingURL=is-mac-os.js.map
@@ -1,6 +1,4 @@
1
- const BODY_METHODS = ["post", "put", "patch", "delete"];
2
- const canMethodHaveBody = (method) => BODY_METHODS.includes(method.toLowerCase());
3
- export {
4
- canMethodHaveBody
5
- };
6
- //# sourceMappingURL=can-method-have-body.js.map
1
+ /** HTTP Methods which can have a body */
2
+ const BODY_METHODS = ['post', 'put', 'patch', 'delete'];
3
+ /** Makes a check to see if this method CAN have a body */
4
+ export const canMethodHaveBody = (method) => BODY_METHODS.includes(method.toLowerCase());
@@ -1,63 +1,65 @@
1
- const REQUEST_METHODS = {
2
- get: {
3
- short: "GET",
4
- colorClass: "text-blue",
5
- colorVar: "var(--scalar-color-blue)",
6
- backgroundColor: "bg-blue/10"
7
- },
8
- post: {
9
- short: "POST",
10
- colorClass: "text-green",
11
- colorVar: "var(--scalar-color-green)",
12
- backgroundColor: "bg-green/10"
13
- },
14
- put: {
15
- short: "PUT",
16
- colorClass: "text-orange",
17
- colorVar: "var(--scalar-color-orange)",
18
- backgroundColor: "bg-orange/10"
19
- },
20
- patch: {
21
- short: "PATCH",
22
- colorClass: "text-yellow",
23
- colorVar: "var(--scalar-color-yellow)",
24
- backgroundColor: "bg-yellow/10"
25
- },
26
- delete: {
27
- short: "DEL",
28
- colorClass: "text-red",
29
- colorVar: "var(--scalar-color-red)",
30
- backgroundColor: "bg-red/10"
31
- },
32
- options: {
33
- short: "OPTS",
34
- colorClass: "text-purple",
35
- colorVar: "var(--scalar-color-purple)",
36
- backgroundColor: "bg-purple/10"
37
- },
38
- head: {
39
- short: "HEAD",
40
- colorClass: "text-c-2",
41
- colorVar: "var(--scalar-color-2)",
42
- backgroundColor: "bg-c-2/10"
43
- },
44
- trace: {
45
- short: "TRACE",
46
- colorClass: "text-c-2",
47
- colorVar: "var(--scalar-color-2)",
48
- backgroundColor: "bg-c-2/10"
49
- }
1
+ /**
2
+ * HTTP methods in a specific order
3
+ * Do not change the order
4
+ */
5
+ export const REQUEST_METHODS = {
6
+ get: {
7
+ short: 'GET',
8
+ colorClass: 'text-blue',
9
+ colorVar: 'var(--scalar-color-blue)',
10
+ backgroundColor: 'bg-blue/10',
11
+ },
12
+ post: {
13
+ short: 'POST',
14
+ colorClass: 'text-green',
15
+ colorVar: 'var(--scalar-color-green)',
16
+ backgroundColor: 'bg-green/10',
17
+ },
18
+ put: {
19
+ short: 'PUT',
20
+ colorClass: 'text-orange',
21
+ colorVar: 'var(--scalar-color-orange)',
22
+ backgroundColor: 'bg-orange/10',
23
+ },
24
+ patch: {
25
+ short: 'PATCH',
26
+ colorClass: 'text-yellow',
27
+ colorVar: 'var(--scalar-color-yellow)',
28
+ backgroundColor: 'bg-yellow/10',
29
+ },
30
+ delete: {
31
+ short: 'DEL',
32
+ colorClass: 'text-red',
33
+ colorVar: 'var(--scalar-color-red)',
34
+ backgroundColor: 'bg-red/10',
35
+ },
36
+ options: {
37
+ short: 'OPTS',
38
+ colorClass: 'text-purple',
39
+ colorVar: 'var(--scalar-color-purple)',
40
+ backgroundColor: 'bg-purple/10',
41
+ },
42
+ head: {
43
+ short: 'HEAD',
44
+ colorClass: 'text-c-2',
45
+ colorVar: 'var(--scalar-color-2)',
46
+ backgroundColor: 'bg-c-2/10',
47
+ },
48
+ trace: {
49
+ short: 'TRACE',
50
+ colorClass: 'text-c-2',
51
+ colorVar: 'var(--scalar-color-2)',
52
+ backgroundColor: 'bg-c-2/10',
53
+ },
50
54
  };
51
- const getHttpMethodInfo = (methodName) => {
52
- const normalizedMethod = methodName.trim().toLowerCase();
53
- return REQUEST_METHODS[normalizedMethod] ?? {
54
- short: normalizedMethod,
55
- color: "text-c-2",
56
- backgroundColor: "bg-c-2"
57
- };
55
+ /**
56
+ * Accepts an HTTP Method name and returns some properties for the tag
57
+ */
58
+ export const getHttpMethodInfo = (methodName) => {
59
+ const normalizedMethod = methodName.trim().toLowerCase();
60
+ return (REQUEST_METHODS[normalizedMethod] ?? {
61
+ short: normalizedMethod,
62
+ color: 'text-c-2',
63
+ backgroundColor: 'bg-c-2',
64
+ });
58
65
  };
59
- export {
60
- REQUEST_METHODS,
61
- getHttpMethodInfo
62
- };
63
- //# sourceMappingURL=http-info.js.map
@@ -1,7 +1,4 @@
1
- const HTTP_METHODS = ["delete", "get", "head", "options", "patch", "post", "put", "trace"];
2
- const httpMethods = Object.freeze(new Set(HTTP_METHODS));
3
- export {
4
- HTTP_METHODS,
5
- httpMethods
6
- };
7
- //# sourceMappingURL=http-methods.js.map
1
+ /** All OpenAPI HTTP methods */
2
+ export const HTTP_METHODS = ['delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'];
3
+ /** Set of all http methods we support */
4
+ export const httpMethods = Object.freeze(new Set(HTTP_METHODS));