@logto/core-kit 2.5.0 → 2.5.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.
@@ -1,4 +1,3 @@
1
1
  /* eslint-disable import/no-unassigned-import */
2
- import './react-app.d';
3
2
  import './dom.d';
4
3
  /* eslint-enable import/no-unassigned-import */
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import { type webcrypto } from 'node:crypto';
3
2
  import { type DeepPartial } from '@silverhand/essentials';
4
3
  import { z } from 'zod';
@@ -1,7 +1,34 @@
1
- export declare const validateRedirectUrl: (url: string, type: 'web' | 'mobile') => boolean;
1
+ export declare const validateRedirectUrl: (url: string, type: "web" | "mobile") => boolean;
2
2
  export declare const validateUriOrigin: (url: string) => boolean;
3
3
  export declare const isValidUrl: (url?: string) => boolean;
4
4
  /**
5
5
  * Check if the given URL is localhost
6
6
  */
7
7
  export declare const isLocalhost: (url: string) => boolean;
8
+ /**
9
+ * Check if the request URL is a file asset path.
10
+ * The check is based on the last segment of the URL path containing a dot, ignoring query params.
11
+ * Example:
12
+ * - `path/scripts.js` -> true
13
+ * - `path/index.html?query=param` -> true
14
+ * - `path` -> false
15
+ * - `path?email=abc@test.com` -> false
16
+ * @param url Request URL
17
+ * @returns Boolean value indicating if the request URL is a file asset path
18
+ */
19
+ export declare const isFileAssetPath: (url: string) => boolean;
20
+ /**
21
+ * Parse the "range" request header value to get the start, end, and count values.
22
+ * Example:
23
+ * - `range: bytes=0-499` -> { start: 0, end: 499, count: 500 }
24
+ * - `range: bytes=0-` -> { start: 0, end: undefined, count: undefined }
25
+ * - `range: invalid` -> Error: Range not satisfiable
26
+ * - Without range header -> { start: undefined, end: undefined, count: undefined }
27
+ * @param range Range request header value
28
+ * @returns Object containing start, end, and count values
29
+ */
30
+ export declare const parseRange: (range: string) => {
31
+ start: number | undefined;
32
+ end: number | undefined;
33
+ count: number | undefined;
34
+ };
package/lib/utils/url.js CHANGED
@@ -32,3 +32,42 @@ export const isLocalhost = (url) => {
32
32
  const parsedUrl = new URL(url);
33
33
  return ['localhost', '127.0.0.1', '::1'].includes(parsedUrl.hostname);
34
34
  };
35
+ /**
36
+ * Check if the request URL is a file asset path.
37
+ * The check is based on the last segment of the URL path containing a dot, ignoring query params.
38
+ * Example:
39
+ * - `path/scripts.js` -> true
40
+ * - `path/index.html?query=param` -> true
41
+ * - `path` -> false
42
+ * - `path?email=abc@test.com` -> false
43
+ * @param url Request URL
44
+ * @returns Boolean value indicating if the request URL is a file asset path
45
+ */
46
+ export const isFileAssetPath = (url) => {
47
+ const pathWithoutQuery = url.split('?')[0];
48
+ return Boolean(pathWithoutQuery?.split('/').at(-1)?.includes('.'));
49
+ };
50
+ /**
51
+ * Parse the "range" request header value to get the start, end, and count values.
52
+ * Example:
53
+ * - `range: bytes=0-499` -> { start: 0, end: 499, count: 500 }
54
+ * - `range: bytes=0-` -> { start: 0, end: undefined, count: undefined }
55
+ * - `range: invalid` -> Error: Range not satisfiable
56
+ * - Without range header -> { start: undefined, end: undefined, count: undefined }
57
+ * @param range Range request header value
58
+ * @returns Object containing start, end, and count values
59
+ */
60
+ export const parseRange = (range) => {
61
+ const rangeMatch = /bytes=(\d+)-(\d+)?/.exec(range);
62
+ if (range && !rangeMatch) {
63
+ throw new Error('Range not satisfiable.');
64
+ }
65
+ const start = rangeMatch?.[1] === undefined ? undefined : Number.parseInt(rangeMatch[1], 10);
66
+ const end = rangeMatch?.[2] === undefined ? undefined : Number.parseInt(rangeMatch[2], 10);
67
+ const count = end === undefined ? undefined : end - (start ?? 0) + 1;
68
+ return {
69
+ start,
70
+ end,
71
+ count,
72
+ };
73
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/core-kit",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "author": "Silverhand Inc. <contact@silverhand.io>",
5
5
  "homepage": "https://github.com/logto-io/toolkit#readme",
6
6
  "repository": {
@@ -39,7 +39,7 @@
39
39
  "color": "^4.2.3"
40
40
  },
41
41
  "optionalDependencies": {
42
- "zod": "^3.22.4"
42
+ "zod": "^3.23.8"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@silverhand/eslint-config": "6.0.1",
@@ -48,15 +48,15 @@
48
48
  "@silverhand/ts-config-react": "6.0.0",
49
49
  "@types/color": "^3.0.3",
50
50
  "@types/node": "^20.9.5",
51
- "@types/react": "^18.0.31",
52
- "@vitest/coverage-v8": "^1.4.0",
51
+ "@types/react": "^18.3.3",
52
+ "@vitest/coverage-v8": "^2.0.0",
53
53
  "eslint": "^8.56.0",
54
54
  "lint-staged": "^15.0.0",
55
55
  "postcss": "^8.4.31",
56
56
  "prettier": "^3.0.0",
57
57
  "stylelint": "^15.0.0",
58
- "typescript": "^5.3.3",
59
- "vitest": "^1.4.0"
58
+ "typescript": "^5.5.3",
59
+ "vitest": "^2.0.0"
60
60
  },
61
61
  "eslintConfig": {
62
62
  "extends": "@silverhand"
@@ -1,65 +0,0 @@
1
- // Copied from react-scripts/lib/react-app.d.ts
2
-
3
- declare module '*.avif' {
4
- const source: string;
5
- export default source;
6
- }
7
-
8
- declare module '*.bmp' {
9
- const source: string;
10
- export default source;
11
- }
12
-
13
- declare module '*.gif' {
14
- const source: string;
15
- export default source;
16
- }
17
-
18
- declare module '*.jpg' {
19
- const source: string;
20
- export default source;
21
- }
22
-
23
- declare module '*.jpeg' {
24
- const source: string;
25
- export default source;
26
- }
27
-
28
- declare module '*.png' {
29
- const source: string;
30
- export default source;
31
- }
32
-
33
- declare module '*.webp' {
34
- const source: string;
35
- export default source;
36
- }
37
-
38
- declare module '*.svg' {
39
- import * as React from 'react';
40
-
41
- export const ReactComponent: React.FunctionComponent<
42
- React.SVGProps<SVGSVGElement> & { title?: string }
43
- >;
44
-
45
- const source: string;
46
- export default source;
47
- }
48
-
49
- declare module '*.module.css' {
50
- const classes: Readonly<Record<string, string>>;
51
- export default classes;
52
- export = classes;
53
- }
54
-
55
- declare module '*.module.scss' {
56
- const classes: Readonly<Record<string, string>>;
57
- export default classes;
58
- export = classes;
59
- }
60
-
61
- declare module '*.module.sass' {
62
- const classes: Readonly<Record<string, string>>;
63
- export default classes;
64
- export = classes;
65
- }
@@ -1,7 +0,0 @@
1
- export declare const buildErrorResponse: (error: unknown) => {
2
- message: string;
3
- stack: string | undefined;
4
- } | {
5
- message: string;
6
- stack?: undefined;
7
- };
@@ -1,9 +0,0 @@
1
- import { types } from 'node:util';
2
- export const buildErrorResponse = (error) =>
3
- /**
4
- * Use `isNativeError` to check if the error is an instance of `Error`.
5
- * If the error comes from `node:vm` module, then it will not be an instance of `Error` but can be captured by `isNativeError`.
6
- */
7
- types.isNativeError(error)
8
- ? { message: error.message, stack: error.stack }
9
- : { message: String(error) };
@@ -1,2 +0,0 @@
1
- export * from './script-execution.js';
2
- export * from './error-handling.js';
@@ -1,2 +0,0 @@
1
- export * from './script-execution.js';
2
- export * from './error-handling.js';
@@ -1,10 +0,0 @@
1
- /**
2
- * This function is used to execute a named function in a customized code script in a local
3
- * virtual machine with the given payload as input.
4
- *
5
- * @param script Custom code snippet.
6
- * @param functionName The name of the function to be executed.
7
- * @param payload The input payload for the function.
8
- * @returns The result of the function execution.
9
- */
10
- export declare const runScriptFunctionInLocalVm: (script: string, functionName: string, payload: unknown) => Promise<unknown>;
@@ -1,30 +0,0 @@
1
- import { runInNewContext } from 'node:vm';
2
- /**
3
- * This function is used to execute a named function in a customized code script in a local
4
- * virtual machine with the given payload as input.
5
- *
6
- * @param script Custom code snippet.
7
- * @param functionName The name of the function to be executed.
8
- * @param payload The input payload for the function.
9
- * @returns The result of the function execution.
10
- */
11
- export const runScriptFunctionInLocalVm = async (script, functionName, payload) => {
12
- const globalContext = Object.freeze({
13
- fetch: async (...args) => fetch(...args),
14
- });
15
- const customFunction = runInNewContext(script + `;${functionName};`, globalContext);
16
- if (typeof customFunction !== 'function') {
17
- throw new TypeError(`The script does not have a function named \`${functionName}\``);
18
- }
19
- /**
20
- * We can not use top-level await in `vm`, use the following implementation instead.
21
- *
22
- * Ref:
23
- * 1. https://github.com/nodejs/node/issues/40898
24
- * 2. https://github.com/n-riesco/ijavascript/issues/173#issuecomment-693924098
25
- */
26
- const result = await runInNewContext('(async () => customFunction(payload))();', Object.freeze({ customFunction, payload }),
27
- // Limit the execution time to 3 seconds, throws error if the script takes too long to execute.
28
- { timeout: 3000 });
29
- return result;
30
- };