Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

remix-utils

Package Overview
Dependencies
Maintainers
0
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

remix-utils - npm Package Compare versions

Comparing version 7.6.0 to 7.7.0

.vscode/extensions.json

46

build/common/promise.js

@@ -70,27 +70,25 @@ /**

*/
export function timeout(promise, options) {
return new Promise(async (resolve, reject) => {
let timer = null;
try {
let result = await Promise.race([
promise,
new Promise((resolve) => {
timer = setTimeout(() => resolve(TIMEOUT), options.ms);
}),
]);
if (timer)
clearTimeout(timer);
if (result === TIMEOUT) {
if (options.controller)
options.controller.abort();
return reject(new TimeoutError(`Timed out after ${options.ms}ms`));
}
return resolve(result);
export async function timeout(promise, options) {
let timer = null;
try {
let result = await Promise.race([
promise,
new Promise((resolve) => {
timer = setTimeout(() => resolve(TIMEOUT), options.ms);
}),
]);
if (timer)
clearTimeout(timer);
if (result === TIMEOUT) {
if (options.controller)
options.controller.abort();
throw new TimeoutError(`Timed out after ${options.ms}ms`);
}
catch (error) {
if (timer)
clearTimeout(timer);
reject(error);
}
});
return result;
}
catch (error) {
if (timer)
clearTimeout(timer);
throw error;
}
}

@@ -97,0 +95,0 @@ /**

@@ -0,3 +1,3 @@

import { useSearchParams } from "@remix-run/react";
import * as React from "react";
import { useSearchParams } from "@remix-run/react";
/**

@@ -4,0 +4,0 @@ * Include existing query params as hidden inputs in a form.

@@ -45,6 +45,8 @@ import * as React from "react";

type?: ScriptType;
/**
* Optional element ID. Use only if the script element needs to be explicitly referenced later.
*/
id?: string;
};
export interface ExternalScriptsFunction<Loader = unknown> {
(args: HandleConventionArguments<Loader>): ScriptDescriptor[];
}
export type ExternalScriptsFunction<Loader = unknown> = (args: HandleConventionArguments<Loader>) => ScriptDescriptor[];
/**

@@ -92,2 +94,2 @@ * Define the shape of the `handle` export if you want to use `scripts`. Combine

export declare function useExternalScripts(): any[];
export declare function ExternalScript({ src, preload, async, defer, crossOrigin, integrity, type, referrerPolicy, noModule, nonce, }: ScriptDescriptor): React.JSX.Element | null;
export declare function ExternalScript({ src, preload, async, defer, crossOrigin, integrity, type, referrerPolicy, noModule, nonce, id, }: ScriptDescriptor): React.JSX.Element | null;

@@ -0,3 +1,3 @@

import { useLocation, useMatches } from "@remix-run/react";
import * as React from "react";
import { useLocation, useMatches } from "@remix-run/react";
import { useHydrated } from "./use-hydrated.js";

@@ -63,3 +63,3 @@ /**

}
export function ExternalScript({ src, preload = false, async = true, defer = true, crossOrigin, integrity, type, referrerPolicy, noModule, nonce, }) {
export function ExternalScript({ src, preload = false, async = true, defer = true, crossOrigin, integrity, type, referrerPolicy, noModule, nonce, id, }) {
let isHydrated = useHydrated();

@@ -81,2 +81,3 @@ let startsHydrated = React.useRef(isHydrated);

nonce,
id,
};

@@ -87,3 +88,3 @@ for (let [key, value] of Object.entries(attributes)) {

}
document.body.append($script);
document.body.appendChild($script);
return () => $script.remove();

@@ -101,2 +102,3 @@ }, [

type,
id,
]);

@@ -109,3 +111,3 @@ if (startsHydrated.current && isHydrated)

preload && (React.createElement("link", { rel: rel, href: src, as: as, crossOrigin: crossOrigin, integrity: integrity, referrerPolicy: referrerPolicy })),
React.createElement("script", { src: src, defer: defer, async: async, type: type, noModule: noModule, nonce: nonce, crossOrigin: crossOrigin, integrity: integrity, referrerPolicy: referrerPolicy })));
React.createElement("script", { id: id, src: src, defer: defer, async: async, type: type, noModule: noModule, nonce: nonce, crossOrigin: crossOrigin, integrity: integrity, referrerPolicy: referrerPolicy })));
}

@@ -0,3 +1,3 @@

import type { Location, Params, useMatches } from "@remix-run/react";
import type { RouterState } from "@remix-run/router";
import type { Location, Params, useMatches } from "@remix-run/react";
export type HandleConventionArguments<Data = unknown> = {

@@ -4,0 +4,0 @@ id: string;

@@ -1,2 +0,2 @@

import type { SubmitOptions, FetcherWithComponents, SubmitFunction } from "@remix-run/react";
import type { FetcherWithComponents, SubmitFunction, SubmitOptions } from "@remix-run/react";
type SubmitTarget = Parameters<SubmitFunction>["0"];

@@ -3,0 +3,0 @@ /**

@@ -12,3 +12,3 @@ import { useFetcher } from "@remix-run/react";

};
}, [timeoutRef]);
}, []);
let fetcher = useFetcher();

@@ -15,0 +15,0 @@ // Clone the original submit to avoid a recursive loop

@@ -1,2 +0,2 @@

import type { SubmitOptions, SubmitFunction } from "@remix-run/react";
import type { SubmitFunction, SubmitOptions } from "@remix-run/react";
type SubmitTarget = Parameters<SubmitFunction>["0"];

@@ -3,0 +3,0 @@ export declare function useDebounceSubmit(): (target: SubmitTarget, options?: SubmitOptions & {

@@ -12,3 +12,3 @@ import { useSubmit } from "@remix-run/react";

};
}, [timeoutRef]);
}, []);
// Clone the original submit to avoid a recursive loop

@@ -15,0 +15,0 @@ const originalSubmit = useSubmit();

@@ -8,3 +8,3 @@ import { PrefetchPageLinks, useNavigate } from "@remix-run/react";

let a = event.target.closest("a");
if (a && a.hasAttribute("href") && a.host === window.location.host)
if (a?.hasAttribute("href") && a.host === window.location.host)
return a;

@@ -11,0 +11,0 @@ return;

@@ -5,2 +5,3 @@ /// <reference types="react" />

event?: string;
enabled?: boolean;
}

@@ -18,2 +19,2 @@ export type EventSourceMap = Map<string, {

*/
export declare function useEventSource(url: string | URL, { event, init }?: EventSourceOptions): string | null;
export declare function useEventSource(url: string | URL, { event, init, enabled }?: EventSourceOptions): string | null;

@@ -1,2 +0,2 @@

import { useEffect, useState, createContext, useContext } from "react";
import { createContext, useContext, useEffect, useState } from "react";
const context = createContext(new Map());

@@ -10,6 +10,9 @@ export const EventSourceProvider = context.Provider;

*/
export function useEventSource(url, { event = "message", init } = {}) {
export function useEventSource(url, { event = "message", init, enabled = true } = {}) {
let map = useContext(context);
let [data, setData] = useState(null);
useEffect(() => {
if (!enabled) {
return undefined;
}
let key = [url.toString(), init?.withCredentials].join("::");

@@ -36,4 +39,4 @@ let value = map.get(key) ?? {

};
}, [url, event, init, map]);
}, [url, event, init, map, enabled]);
return data;
}

@@ -1,2 +0,2 @@

import { useNavigation, useFetchers, useRevalidator } from "@remix-run/react";
import { useFetchers, useNavigation, useRevalidator } from "@remix-run/react";
import { useMemo } from "react";

@@ -3,0 +3,0 @@ /**

import { useSyncExternalStore } from "react";
function subscribe() {
// biome-ignore lint/suspicious/noEmptyBlockStatements: Mock function
return () => { };

@@ -4,0 +5,0 @@ }

@@ -36,3 +36,3 @@ const DEFAULT_OPTIONS = {

configureMaxAge(headers) {
var { maxAge } = this.options;
const { maxAge } = this.options;
if (!this.isNumber(maxAge))

@@ -39,0 +39,0 @@ return headers;

@@ -101,7 +101,6 @@ import cryptoJS from "crypto-js";

parseCookie(data, headers) {
if (data instanceof Request)
headers = data.headers;
if (!headers)
let _headers = data instanceof Request ? data.headers : headers;
if (!_headers)
return null;
return this.cookie.parse(headers.get("cookie"));
return this.cookie.parse(_headers.get("cookie"));
}

@@ -108,0 +107,0 @@ sign(token) {

@@ -8,14 +8,6 @@ interface SendFunctionArgs {

}
interface SendFunction {
(args: SendFunctionArgs): void;
}
interface CleanupFunction {
(): void;
}
interface AbortFunction {
(): void;
}
interface InitFunction {
(send: SendFunction, abort: AbortFunction): CleanupFunction;
}
type SendFunction = (args: SendFunctionArgs) => void;
type CleanupFunction = () => void;
type AbortFunction = () => void;
type InitFunction = (send: SendFunction, abort: AbortFunction) => CleanupFunction;
/**

@@ -22,0 +14,0 @@ * A response helper to use Server Sent Events server-side

@@ -48,5 +48,4 @@ import { isIP } from "is-ip";

return part.slice(4);
continue;
}
return null;
}
export interface HoneypotInputProps {
/**
* The name expected to be used by the honeypot input field.
*/
nameFieldName: string;
/**
* The name expected to be used by the honeypot valid from input field.
*/
validFromFieldName: string | null;
/**
* The encrypted value of the current timestamp.
*/
encryptedValidFrom: string;
}
export interface HoneypotConfig {
/**
* Enable randomization of the name field name, this way the honeypot field
* name will be different for each request.
*/
randomizeNameFieldName?: boolean;
/**
* The name of the field that will be used for the honeypot input.
*/
nameFieldName?: string;
/**
* The name of the field that will be used for the honeypot valid from input.
*/
validFromFieldName?: string | null;
/**
* The seed used for the encryption of the valid from timestamp.
*/
encryptionSeed?: string;
}
/**
* The error thrown when the Honeypot fails, meaning some automated bot filled
* the form and the request is probably spam.
*/
export declare class SpamError extends Error {
readonly name = "SpamError";
}
/**
* Module used to implement a Honeypot.
* A Honeypot is a visually hidden input that is used to detect spam bots. This
* field is expected to be left empty by users because they don't see it, but
* bots will fill it falling in the honeypot trap.
*/
export declare class Honeypot {
private generatedEncryptionSeed;
protected config: HoneypotConfig;
private generatedEncryptionSeed;
constructor(config?: HoneypotConfig);
/**
* Get the HoneypotInputProps to be used in your forms.
* @param {Object} options The options for the input props.
* @param {number} options.validFromTimestamp Since when the timestamp is valid.
* @returns {HoneypotInputProps} The props to be used in the form.
*/
getInputProps({ validFromTimestamp, }?: {

@@ -19,0 +58,0 @@ validFromTimestamp?: number | undefined;

import CryptoJS from "crypto-js";
/**
* The error thrown when the Honeypot fails, meaning some automated bot filled
* the form and the request is probably spam.
*/
export class SpamError extends Error {
name = "SpamError";
}
const DEFAULT_NAME_FIELD_NAME = "name__confirm";
const DEFAULT_VALID_FROM_FIELD_NAME = "from__confirm";
/**
* Module used to implement a Honeypot.
* A Honeypot is a visually hidden input that is used to detect spam bots. This
* field is expected to be left empty by users because they don't see it, but
* bots will fill it falling in the honeypot trap.
*/
export class Honeypot {
generatedEncryptionSeed = this.randomValue();
config;
generatedEncryptionSeed = this.randomValue();
constructor(config = {}) {
this.config = config;
}
/**
* Get the HoneypotInputProps to be used in your forms.
* @param {Object} options The options for the input props.
* @param {number} options.validFromTimestamp Since when the timestamp is valid.
* @returns {HoneypotInputProps} The props to be used in the form.
*/
getInputProps({ validFromTimestamp = Date.now(), } = {}) {

@@ -13,0 +30,0 @@ return {

@@ -7,3 +7,3 @@ export async function namedAction(input, actions) {

if (name === null && "default" in actions) {
return actions["default"]();
return actions.default();
}

@@ -10,0 +10,0 @@ if (name === null)

@@ -60,2 +60,4 @@ /**

let route = context.routeModules[match.route.id];
if (!route)
return [];
if (route.links instanceof Function)

@@ -62,0 +64,0 @@ return route.links();

@@ -19,5 +19,4 @@ import { getHeaders } from "./get-headers.js";

return handler();
continue;
}
return handlers.default();
}

@@ -14,10 +14,10 @@ const DEFAULT_REDIRECT = "/";

return defaultRedirect;
to = to.trim();
if (!to.startsWith("/") ||
to.startsWith("//") ||
to.startsWith("/\\") ||
to.includes("..")) {
let trimmedTo = to.trim();
if (!trimmedTo.startsWith("/") ||
trimmedTo.startsWith("//") ||
trimmedTo.startsWith("/\\") ||
trimmedTo.includes("..")) {
return defaultRedirect;
}
return to;
return trimmedTo;
}

@@ -6,3 +6,3 @@ import { Cookie, CookieParseOptions, CookieSerializeOptions } from "@remix-run/server-runtime";

parse(cookieHeader: string | null, options?: CookieParseOptions): Promise<z.infer<Schema> | null>;
serialize(value: z.infer<Schema>, options?: CookieSerializeOptions): Promise<string>;
serialize(value: z.input<Schema>, options?: CookieSerializeOptions): Promise<string>;
}

@@ -9,0 +9,0 @@ export declare function createTypedCookie<Schema extends z.ZodTypeAny>({ cookie, schema, }: {

{
"name": "remix-utils",
"version": "7.6.0",
"version": "7.7.0",
"license": "MIT",

@@ -9,2 +9,5 @@ "engines": {

"type": "module",
"funding": [
"https://github.com/sponsors/sergiodxa"
],
"exports": {

@@ -54,6 +57,6 @@ "./package.json": "./package.json",

"build": "tsc --project tsconfig.json --outDir ./build",
"postbuild": "prettier --write \"build/**/*.js\" \"build/**/*.d.ts\"",
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.tsx\" \"test/**/*.ts\" \"test/**/*.tsx\" \"*.md\" \"package.json\"",
"format": "biome format --write .",
"typecheck": "tsc --project tsconfig.json --noEmit",
"lint": "eslint --ext .ts,.tsx src/",
"check": "biome check .",
"lint": "biome lint .",
"test": "vitest --run",

@@ -98,3 +101,2 @@ "test:watch": "vitest",

"@remix-run/cloudflare": "^2.0.0",
"@remix-run/deno": "^2.0.0",
"@remix-run/node": "^2.0.0",

@@ -113,5 +115,2 @@ "@remix-run/react": "^2.0.0",

},
"@remix-run/deno": {
"optional": true
},
"@remix-run/node": {

@@ -144,2 +143,3 @@ "optional": true

"@arethetypeswrong/cli": "^0.15.0",
"@biomejs/biome": "^1.7.2",
"@remix-run/node": "^2.0.0",

@@ -150,39 +150,26 @@ "@remix-run/react": "^2.0.0",

"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@testing-library/react": "^15.0.2",
"@types/bun": "^1.1.1",
"@types/crypto-js": "^4.1.2",
"@types/react": "^18.2.25",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.1",
"@vitejs/plugin-react": "^4.1.0",
"@vitest/coverage-v8": "^1.3.1",
"@types/react": "^18.2.78",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.5.0",
"crypto-js": "^4.1.1",
"eslint": "^8.12.0",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jest-dom": "^5.1.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-testing-library": "^6.0.2",
"eslint-plugin-unicorn": "^52.0.0",
"happy-dom": "^14.3.6",
"happy-dom": "^14.7.1",
"intl-parse-accept-language": "^1.0.0",
"is-ip": "5.0.1",
"msw": "^2.0.0",
"prettier": "^3.0.3",
"msw": "^2.2.13",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"ts-node": "^10.9.1",
"typedoc": "^0.25.13",
"typedoc-plugin-mdn-links": "^3.1.23",
"typescript": "^5.2.2",
"vite": "^5.0.0",
"vitest": "^0.34.6",
"vite": "^5.2.8",
"vitest": "^1.4.0",
"zod": "^3.22.4"
},
"dependencies": {
"type-fest": "^4.3.3"
"type-fest": "^4.18.1"
}
}

@@ -1,5 +0,5 @@

/* eslint-disable unicorn/no-process-exit */
import { file, spawn } from "bun";
async function main() {
const proc = Bun.spawn([
let proc = spawn([
"bunx",

@@ -14,5 +14,5 @@ "attw",

const text = await new Response(proc.stdout).text();
let text = await new Response(proc.stdout).text();
const entrypointLines = text
let entrypointLines = text
.slice(text.indexOf('"remix-utils/'))

@@ -30,5 +30,5 @@ .split("\n")

const pkg = await Bun.file("package.json").json();
const entrypoints = entrypointLines.map((entrypointLine) => {
const [entrypoint, ...resolutionColumns] = entrypointLine.split("│");
let pkg = await file("package.json").json();
let entrypoints = entrypointLines.map((entrypointLine) => {
let [entrypoint, ...resolutionColumns] = entrypointLine.split("│");
return {

@@ -41,18 +41,9 @@ entrypoint: entrypoint.replace(pkg.name, ".").trim(),

const entrypointsWithProblems = entrypoints.filter(
let entrypointsWithProblems = entrypoints.filter(
(item) => item.esm.includes("fail") || item.bundler.includes("fail"),
);
if (entrypointsWithProblems.length > 0) {
console.error("Entrypoints with problems:");
console.log(
`---\n${entrypointsWithProblems
.map(
({ entrypoint, esm, bundler }) =>
`entrypoint: ${entrypoint}\nesm: ${esm}\nbundler: ${bundler}`,
)
.join("\n---\n")}\n---`,
);
process.exit(1);
} else {
console.log("No problems found.");
}

@@ -59,0 +50,0 @@ }

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc