Bump rails requestjs version

This commit is contained in:
Thiago Youssef
2025-12-17 20:18:38 -03:00
parent 9d29b4d316
commit bd0a749f22
3 changed files with 5 additions and 309 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js" pin "@hotwired/turbo-rails", to: "turbo.min.js"
pin "@hotwired/stimulus", to: "stimulus.min.js" pin "@hotwired/stimulus", to: "stimulus.min.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js" pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
pin "@rails/request.js", to: "rails-request.js" # @0.0.11 pin "@rails/request.js", to: "@rails--request.js" # @0.0.13
pin_all_from "app/javascript/controllers", under: "controllers" pin_all_from "app/javascript/controllers", under: "controllers"
pin_all_from "app/javascript/helpers", under: "helpers" pin_all_from "app/javascript/helpers", under: "helpers"
File diff suppressed because one or more lines are too long
-308
View File
@@ -1,308 +0,0 @@
// Patched to use Turbo.fetch. @TODO Upstream this.
class FetchResponse {
constructor(response) {
this.response = response;
}
get statusCode() {
return this.response.status;
}
get redirected() {
return this.response.redirected;
}
get ok() {
return this.response.ok;
}
get unauthenticated() {
return this.statusCode === 401;
}
get unprocessableEntity() {
return this.statusCode === 422;
}
get authenticationURL() {
return this.response.headers.get("WWW-Authenticate");
}
get contentType() {
const contentType = this.response.headers.get("Content-Type") || "";
return contentType.replace(/;.*$/, "");
}
get headers() {
return this.response.headers;
}
get html() {
if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
return this.text;
}
return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`));
}
get json() {
if (this.contentType.match(/^application\/.*json$/)) {
return this.responseJson || (this.responseJson = this.response.json());
}
return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`));
}
get text() {
return this.responseText || (this.responseText = this.response.text());
}
get isTurboStream() {
return this.contentType.match(/^text\/vnd\.turbo-stream\.html/);
}
get isScript() {
return this.contentType.match(/\b(?:java|ecma)script\b/);
}
async renderTurboStream() {
if (this.isTurboStream) {
if (window.Turbo) {
await window.Turbo.renderStreamMessage(await this.text);
} else {
console.warn("You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js");
}
} else {
return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`));
}
}
async activeScript() {
if (this.isScript) {
const script = document.createElement("script");
const metaTag = document.querySelector("meta[name=csp-nonce]");
if (metaTag) {
const nonce = metaTag.nonce === "" ? metaTag.content : metaTag.nonce;
if (nonce) {
script.setAttribute("nonce", nonce);
}
}
script.innerHTML = await this.text;
document.body.appendChild(script);
} else {
return Promise.reject(new Error(`Expected a Script response but got "${this.contentType}" instead`));
}
}
}
class RequestInterceptor {
static register(interceptor) {
this.interceptor = interceptor;
}
static get() {
return this.interceptor;
}
static reset() {
this.interceptor = undefined;
}
}
function getCookie(name) {
const cookies = document.cookie ? document.cookie.split("; ") : [];
const prefix = `${encodeURIComponent(name)}=`;
const cookie = cookies.find((cookie => cookie.startsWith(prefix)));
if (cookie) {
const value = cookie.split("=").slice(1).join("=");
if (value) {
return decodeURIComponent(value);
}
}
}
function compact(object) {
const result = {};
for (const key in object) {
const value = object[key];
if (value !== undefined) {
result[key] = value;
}
}
return result;
}
function metaContent(name) {
const element = document.head.querySelector(`meta[name="${name}"]`);
return element && element.content;
}
function stringEntriesFromFormData(formData) {
return [ ...formData ].reduce(((entries, [name, value]) => entries.concat(typeof value === "string" ? [ [ name, value ] ] : [])), []);
}
function mergeEntries(searchParams, entries) {
for (const [name, value] of entries) {
if (value instanceof window.File) continue;
if (searchParams.has(name) && !name.includes("[]")) {
searchParams.delete(name);
searchParams.set(name, value);
} else {
searchParams.append(name, value);
}
}
}
class FetchRequest {
constructor(method, url, options = {}) {
this.method = method;
this.options = options;
this.originalUrl = url.toString();
}
async perform() {
try {
const requestInterceptor = RequestInterceptor.get();
if (requestInterceptor) {
await requestInterceptor(this);
}
} catch (error) {
console.error(error);
}
const fetch = this.responseKind === "turbo-stream" && window.Turbo ? window.Turbo.fetch : window.fetch;
const response = new FetchResponse(await Turbo.fetch(this.url, this.fetchOptions));
if (response.unauthenticated && response.authenticationURL) {
return Promise.reject(window.location.href = response.authenticationURL);
}
if (response.isScript) {
await response.activeScript();
}
const responseStatusIsTurboStreamable = response.ok || response.unprocessableEntity;
if (responseStatusIsTurboStreamable && response.isTurboStream) {
await response.renderTurboStream();
}
return response;
}
addHeader(key, value) {
const headers = this.additionalHeaders;
headers[key] = value;
this.options.headers = headers;
}
sameHostname() {
if (!this.originalUrl.startsWith("http:") && !this.originalUrl.startsWith("https:")) {
return true;
}
try {
return new URL(this.originalUrl).hostname === window.location.hostname;
} catch (_) {
return true;
}
}
get fetchOptions() {
return {
method: this.method.toUpperCase(),
headers: this.headers,
body: this.formattedBody,
signal: this.signal,
credentials: this.credentials,
redirect: this.redirect,
keepalive: this.keepalive
};
}
get headers() {
const baseHeaders = {
"X-Requested-With": "XMLHttpRequest",
"Content-Type": this.contentType,
Accept: this.accept
};
if (this.sameHostname()) {
baseHeaders["X-CSRF-Token"] = this.csrfToken;
}
return compact(Object.assign(baseHeaders, this.additionalHeaders));
}
get csrfToken() {
return getCookie(metaContent("csrf-param")) || metaContent("csrf-token");
}
get contentType() {
if (this.options.contentType) {
return this.options.contentType;
} else if (this.body == null || this.body instanceof window.FormData) {
return undefined;
} else if (this.body instanceof window.File) {
return this.body.type;
}
return "application/json";
}
get accept() {
switch (this.responseKind) {
case "html":
return "text/html, application/xhtml+xml";
case "turbo-stream":
return "text/vnd.turbo-stream.html, text/html, application/xhtml+xml";
case "json":
return "application/json, application/vnd.api+json";
case "script":
return "text/javascript, application/javascript";
default:
return "*/*";
}
}
get body() {
return this.options.body;
}
get query() {
const originalQuery = (this.originalUrl.split("?")[1] || "").split("#")[0];
const params = new URLSearchParams(originalQuery);
let requestQuery = this.options.query;
if (requestQuery instanceof window.FormData) {
requestQuery = stringEntriesFromFormData(requestQuery);
} else if (requestQuery instanceof window.URLSearchParams) {
requestQuery = requestQuery.entries();
} else {
requestQuery = Object.entries(requestQuery || {});
}
mergeEntries(params, requestQuery);
const query = params.toString();
return query.length > 0 ? `?${query}` : "";
}
get url() {
return this.originalUrl.split("?")[0].split("#")[0] + this.query;
}
get responseKind() {
return this.options.responseKind || "html";
}
get signal() {
return this.options.signal;
}
get redirect() {
return this.options.redirect || "follow";
}
get credentials() {
return this.options.credentials || "same-origin";
}
get keepalive() {
return this.options.keepalive || false;
}
get additionalHeaders() {
return this.options.headers || {};
}
get formattedBody() {
const bodyIsAString = Object.prototype.toString.call(this.body) === "[object String]";
const contentTypeIsJson = this.headers["Content-Type"] === "application/json";
if (contentTypeIsJson && !bodyIsAString) {
return JSON.stringify(this.body);
}
return this.body;
}
}
async function get(url, options) {
const request = new FetchRequest("get", url, options);
return request.perform();
}
async function post(url, options) {
const request = new FetchRequest("post", url, options);
return request.perform();
}
async function put(url, options) {
const request = new FetchRequest("put", url, options);
return request.perform();
}
async function patch(url, options) {
const request = new FetchRequest("patch", url, options);
return request.perform();
}
async function destroy(url, options) {
const request = new FetchRequest("delete", url, options);
return request.perform();
}
export { FetchRequest, FetchResponse, RequestInterceptor, destroy, get, patch, post, put };