UNPKG

@astro-utils/forms

Version:

Server component for Astro (call server functions from client side with validation and state management)

124 lines (123 loc) 4.22 kB
import getContext from '@astro-utils/context'; export default class FormsReact { constructor(_astro) { this._astro = _astro; this.scriptToRun = ''; this.overrideResponse = null; } /** * Reload the state (BindForm) without client redirect. If that a POST request, buttons will not be invoked again. * Call BindForm.on.reloadState() to reload the state of every form relevant to this reload. */ reloadState() { const { settings } = getContext(this._astro, '@astro-utils/forms'); settings.reloadState = true; } /** * Redirects the user to the given URL after the given timeout. (using `setTimeout`) * @param location * @param timeoutSec - timeout in seconds */ redirectTimeoutSeconds(location, timeoutSec = 2) { this.scriptToRun += ` setTimeout(function() { window.location.href = new URL("${this._escapeParentheses(location)}", window.location.href).href; }, ${timeoutSec * 1000}); `.trim(); } /** * Redirect the user to the given URL. * @param location * @param status - redirect status code */ redirect(location, status) { this.overrideResponse = new Response(null, { status: status || 302, headers: { Location: location, }, }); } /** * Update the search parameters of the current URL and return `Response` object. */ updateSearchParams() { const url = new URL(this._astro.request.url, 'http://example.com'); const search = url.searchParams; const self = this; return { search, redirect(status, removeEmptyParams = true) { const copySearch = new URLSearchParams(search); if (removeEmptyParams) { for (const [key, value] of copySearch.entries()) { if (value === '' || value == null) { copySearch.delete(key); } } } const searchString = copySearch.toString(); let pathWithSearch = url.pathname.split('/').pop(); if (searchString) { pathWithSearch += '?' + searchString; } self.overrideResponse = new Response(null, { status: status || 302, headers: { Location: pathWithSearch, }, }); } }; } /** * Update **one** search parameter of the current URL and return `Response` object. * @param key - search parameter key * @param value - search parameter value (if `null` the parameter will be removed) * @param status - redirect status code */ updateOneSearchParam(key, value, status) { const { search, redirect } = this.updateSearchParams(); if (value == null) { search.delete(key); } else { search.set(key, value); } redirect(status); } /** * Prompt alert message to the user with the `window.alert` function. * @param message */ alert(message) { this.callFunction('alert', message); } /** * Print a message to the client console with the `console` class. */ console(type, ...messages) { if (!(type in console)) { throw new Error(`Invalid console type: ${type}`); } this.callFunction(`console.${type}`, ...messages); } /** * Print a message to the client console with the `console.log` function. */ consoleLog(...messages) { this.console('log', ...messages); } /** * Call a client side function with the given arguments. * @warning - this is **not** a safe function, make sure to validate the arguments before calling this function. */ callFunction(func, ...args) { this.scriptToRun += ` ${func}(...${JSON.stringify(args)}); `.trim(); } _escapeParentheses(str) { return str.replace(/"/g, '\\"'); } }