frappe-sdk-react-i4z
Version:
React hooks library for Frappe Framework
747 lines (746 loc) • 22 kB
JavaScript
import oe, { createContext as ce, useState as y, useEffect as W, useContext as ie, useCallback as _ } from "react";
import U from "swr";
var P = { exports: {} }, O = {};
/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var q;
function le() {
if (q) return O;
q = 1;
var c = Symbol.for("react.transitional.element"), r = Symbol.for("react.fragment");
function t(n, a, s) {
var l = null;
if (s !== void 0 && (l = "" + s), a.key !== void 0 && (l = "" + a.key), "key" in a) {
s = {};
for (var i in a)
i !== "key" && (s[i] = a[i]);
} else s = a;
return a = s.ref, {
$$typeof: c,
type: n,
key: l,
ref: a !== void 0 ? a : null,
props: s
};
}
return O.Fragment = r, O.jsx = t, O.jsxs = t, O;
}
var D = {};
/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var z;
function ue() {
return z || (z = 1, process.env.NODE_ENV !== "production" && (function() {
function c(e) {
if (e == null) return null;
if (typeof e == "function")
return e.$$typeof === ne ? null : e.displayName || e.name || null;
if (typeof e == "string") return e;
switch (e) {
case T:
return "Fragment";
case X:
return "Profiler";
case x:
return "StrictMode";
case K:
return "Suspense";
case ee:
return "SuspenseList";
case re:
return "Activity";
}
if (typeof e == "object")
switch (typeof e.tag == "number" && console.error(
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
), e.$$typeof) {
case g:
return "Portal";
case B:
return (e.displayName || "Context") + ".Provider";
case Q:
return (e._context.displayName || "Context") + ".Consumer";
case Z:
var u = e.render;
return e = e.displayName, e || (e = u.displayName || u.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
case te:
return u = e.displayName || null, u !== null ? u : c(e.type) || "Memo";
case F:
u = e._payload, e = e._init;
try {
return c(e(u));
} catch {
}
}
return null;
}
function r(e) {
return "" + e;
}
function t(e) {
try {
r(e);
var u = !1;
} catch {
u = !0;
}
if (u) {
u = console;
var m = u.error, w = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
return m.call(
u,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
w
), r(e);
}
}
function n(e) {
if (e === T) return "<>";
if (typeof e == "object" && e !== null && e.$$typeof === F)
return "<...>";
try {
var u = c(e);
return u ? "<" + u + ">" : "<...>";
} catch {
return "<...>";
}
}
function a() {
var e = A.A;
return e === null ? null : e.getOwner();
}
function s() {
return Error("react-stack-top-frame");
}
function l(e) {
if (L.call(e, "key")) {
var u = Object.getOwnPropertyDescriptor(e, "key").get;
if (u && u.isReactWarning) return !1;
}
return e.key !== void 0;
}
function i(e, u) {
function m() {
I || (I = !0, console.error(
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
u
));
}
m.isReactWarning = !0, Object.defineProperty(e, "key", {
get: m,
configurable: !0
});
}
function o() {
var e = c(this.type);
return Y[e] || (Y[e] = !0, console.error(
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
)), e = this.props.ref, e !== void 0 ? e : null;
}
function d(e, u, m, w, S, R, $, j) {
return m = R.ref, e = {
$$typeof: E,
type: e,
key: u,
props: R,
_owner: S
}, (m !== void 0 ? m : null) !== null ? Object.defineProperty(e, "ref", {
enumerable: !1,
get: o
}) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
configurable: !1,
enumerable: !1,
writable: !0,
value: 0
}), Object.defineProperty(e, "_debugInfo", {
configurable: !1,
enumerable: !1,
writable: !0,
value: null
}), Object.defineProperty(e, "_debugStack", {
configurable: !1,
enumerable: !1,
writable: !0,
value: $
}), Object.defineProperty(e, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: j
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
}
function p(e, u, m, w, S, R, $, j) {
var b = u.children;
if (b !== void 0)
if (w)
if (se(b)) {
for (w = 0; w < b.length; w++)
f(b[w]);
Object.freeze && Object.freeze(b);
} else
console.error(
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
);
else f(b);
if (L.call(u, "key")) {
b = c(e);
var v = Object.keys(u).filter(function(ae) {
return ae !== "key";
});
w = 0 < v.length ? "{key: someKey, " + v.join(": ..., ") + ": ...}" : "{key: someKey}", M[b + w] || (v = 0 < v.length ? "{" + v.join(": ..., ") + ": ...}" : "{}", console.error(
`A props object containing a "key" prop is being spread into JSX:
let props = %s;
<%s {...props} />
React keys must be passed directly to JSX without using spread:
let props = %s;
<%s key={someKey} {...props} />`,
w,
b,
v,
b
), M[b + w] = !0);
}
if (b = null, m !== void 0 && (t(m), b = "" + m), l(u) && (t(u.key), b = "" + u.key), "key" in u) {
m = {};
for (var N in u)
N !== "key" && (m[N] = u[N]);
} else m = u;
return b && i(
m,
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
), d(
e,
b,
R,
S,
a(),
m,
$,
j
);
}
function f(e) {
typeof e == "object" && e !== null && e.$$typeof === E && e._store && (e._store.validated = 1);
}
var h = oe, E = Symbol.for("react.transitional.element"), g = Symbol.for("react.portal"), T = Symbol.for("react.fragment"), x = Symbol.for("react.strict_mode"), X = Symbol.for("react.profiler"), Q = Symbol.for("react.consumer"), B = Symbol.for("react.context"), Z = Symbol.for("react.forward_ref"), K = Symbol.for("react.suspense"), ee = Symbol.for("react.suspense_list"), te = Symbol.for("react.memo"), F = Symbol.for("react.lazy"), re = Symbol.for("react.activity"), ne = Symbol.for("react.client.reference"), A = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, L = Object.prototype.hasOwnProperty, se = Array.isArray, C = console.createTask ? console.createTask : function() {
return null;
};
h = {
react_stack_bottom_frame: function(e) {
return e();
}
};
var I, Y = {}, J = h.react_stack_bottom_frame.bind(
h,
s
)(), G = C(n(s)), M = {};
D.Fragment = T, D.jsx = function(e, u, m, w, S) {
var R = 1e4 > A.recentlyCreatedOwnerStacks++;
return p(
e,
u,
m,
!1,
w,
S,
R ? Error("react-stack-top-frame") : J,
R ? C(n(e)) : G
);
}, D.jsxs = function(e, u, m, w, S) {
var R = 1e4 > A.recentlyCreatedOwnerStacks++;
return p(
e,
u,
m,
!0,
w,
S,
R ? Error("react-stack-top-frame") : J,
R ? C(n(e)) : G
);
};
})()), D;
}
var H;
function de() {
return H || (H = 1, process.env.NODE_ENV === "production" ? P.exports = le() : P.exports = ue()), P.exports;
}
var fe = de();
class pe {
baseUrl;
token;
useToken;
constructor(r = {}) {
this.baseUrl = r.url || (typeof window < "u" ? window.location.origin : ""), this.useToken = r.useToken || !1, this.token = r.tokenParams?.token;
}
getHeaders() {
const r = {
"Content-Type": "application/json",
Accept: "application/json"
};
return this.useToken && this.token && (r.Authorization = `token ${this.token}`), r;
}
async handleResponse(r) {
const t = await r.json();
if (!r.ok)
throw {
message: t.message || t.exc || "An error occurred",
exception: t.exception,
exc_type: t.exc_type,
indicator: t.indicator
};
return t.message || t;
}
async call(r) {
const { method: t, args: n = {}, httpMethod: a = "POST" } = r, s = `${this.baseUrl}/api/method/${t}`;
if (a === "GET") {
const i = new URLSearchParams();
Object.entries(n).forEach(([p, f]) => {
i.append(p, JSON.stringify(f));
});
const o = i.toString() ? `${s}?${i.toString()}` : s, d = await fetch(o, {
method: "GET",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include"
});
return this.handleResponse(d);
}
const l = await fetch(s, {
method: "POST",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include",
body: JSON.stringify(n)
});
return this.handleResponse(l);
}
async login(r, t) {
const n = await fetch(`${this.baseUrl}/api/method/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
credentials: "include",
body: JSON.stringify({ usr: r, pwd: t })
});
return this.handleResponse(n);
}
async logout() {
const r = await fetch(`${this.baseUrl}/api/method/logout`, {
method: "POST",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include"
});
await this.handleResponse(r);
}
async getCurrentUser() {
return this.call({
method: "frappe.auth.get_logged_user"
});
}
async getDoc(r, t) {
const n = await fetch(
`${this.baseUrl}/api/resource/${r}/${encodeURIComponent(t)}`,
{
method: "GET",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include"
}
);
return (await this.handleResponse(n)).data;
}
async getDocList(r) {
const {
doctype: t,
fields: n = ["*"],
filters: a = {},
or_filters: s,
order_by: l,
limit_start: i = 0,
limit_page_length: o = 20,
group_by: d,
parent: p
} = r, f = new URLSearchParams({
fields: JSON.stringify(n),
filters: JSON.stringify(a),
limit_start: i.toString(),
limit_page_length: o.toString()
});
s && f.append("or_filters", JSON.stringify(s)), l && f.append("order_by", l), d && f.append("group_by", d), p && f.append("parent", p);
const h = await fetch(`${this.baseUrl}/api/resource/${t}?${f.toString()}`, {
method: "GET",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include"
});
return (await this.handleResponse(h)).data;
}
async getDocCount(r) {
const { doctype: t, filters: n = {}, cache: a = !0 } = r, s = new URLSearchParams({
filters: JSON.stringify(n),
cache: a.toString()
}), l = await fetch(`${this.baseUrl}/api/resource/${t}?${s.toString()}&limit_page_length=1&fields=["name"]`, {
method: "GET",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include"
});
return (await this.handleResponse(l)).count || 0;
}
async createDoc(r) {
const { doctype: t, doc: n } = r, a = await fetch(`${this.baseUrl}/api/resource/${t}`, {
method: "POST",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include",
body: JSON.stringify(n)
});
return (await this.handleResponse(a)).data;
}
async updateDoc(r) {
const { doctype: t, name: n, doc: a } = r, s = await fetch(`${this.baseUrl}/api/resource/${t}/${encodeURIComponent(n)}`, {
method: "PUT",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include",
body: JSON.stringify(a)
});
return (await this.handleResponse(s)).data;
}
async deleteDoc(r) {
const { doctype: t, name: n } = r, a = await fetch(`${this.baseUrl}/api/resource/${t}/${encodeURIComponent(n)}`, {
method: "DELETE",
headers: this.getHeaders(),
credentials: this.useToken ? "omit" : "include"
});
await this.handleResponse(a);
}
async uploadFile(r) {
const { file: t, is_private: n = !1, doctype: a, docname: s, fieldname: l } = r, i = new FormData();
i.append("file", t), i.append("is_private", n.toString()), a && i.append("doctype", a), s && i.append("docname", s), l && i.append("fieldname", l);
const o = {};
this.useToken && this.token && (o.Authorization = `token ${this.token}`);
const d = await fetch(`${this.baseUrl}/api/method/upload_file`, {
method: "POST",
headers: o,
credentials: this.useToken ? "omit" : "include",
body: i
});
return this.handleResponse(d);
}
async searchLink(r, t, n = {}) {
return this.call({
method: "frappe.desk.search.search_link",
args: {
doctype: r,
txt: t,
filters: n
}
});
}
}
const V = ce(null), ge = ({ children: c, config: r = {} }) => {
const [t] = y(() => new pe(r)), [n, a] = y(null), [s, l] = y(!1);
W(() => {
const o = async () => {
try {
const d = await t.getCurrentUser();
a(d), l(!0);
} catch {
a(null), l(!1);
}
};
r.useToken ? r.tokenParams?.token && l(!0) : o();
}, [t, r.useToken, r.tokenParams?.token]);
const i = {
url: t.baseUrl,
call: async (o) => t.call(o),
db: {
getDoc: async (o, d) => t.getDoc(o, d),
getDocList: async (o) => t.getDocList(o),
getDocCount: async (o) => t.getDocCount(o),
createDoc: async (o) => t.createDoc(o),
updateDoc: async (o) => t.updateDoc(o),
deleteDoc: async (o) => t.deleteDoc(o)
},
auth: {
login: async (o, d) => {
const p = await t.login(o, d);
try {
const f = await t.getCurrentUser();
a(f), l(!0);
} catch (f) {
console.error("Failed to get user after login:", f);
}
return p;
},
logout: async () => {
await t.logout(), a(null), l(!1);
},
getUser: async () => {
const o = await t.getCurrentUser();
return a(o), o;
},
currentUser: n,
isLoggedIn: s
},
file: {
upload: async (o) => t.uploadFile(o)
}
};
return /* @__PURE__ */ fe.jsx(V.Provider, { value: i, children: c });
}, k = () => {
const c = ie(V);
if (!c)
throw new Error("useFrappeContext must be used within a FrappeProvider");
return c;
}, ye = () => {
const { auth: c } = k();
return c;
}, Ee = (c, r, t = "POST") => {
const { call: n } = k(), [a, s] = y(null), [l, i] = y(null), [o, d] = y(!1), p = _(
async (h = {}) => {
if (!c && !h.method)
throw new Error("Method is required");
const E = {
method: h.method || c,
args: { ...r, ...h.args },
httpMethod: h.httpMethod || t
};
d(!0), i(null);
try {
const g = await n(E);
return s(g), g;
} catch (g) {
const T = g instanceof Error ? g : new Error(String(g));
throw i(T), T;
} finally {
d(!1);
}
},
[n, c, r, t]
), f = _(() => {
s(null), i(null), d(!1);
}, []);
return { call: p, data: a, error: l, loading: o, reset: f };
}, we = (c) => {
const { db: r } = k(), [t, n] = y(null), [a, s] = y(null), [l, i] = y(!1), o = _(
async (p) => {
if (!c)
throw new Error("Doctype is required");
const f = { doctype: c, doc: p };
i(!0), s(null);
try {
const h = await r.createDoc(f);
return n(h), h;
} catch (h) {
const E = h instanceof Error ? h : new Error(String(h));
throw s(E), E;
} finally {
i(!1);
}
},
[r, c]
), d = _(() => {
n(null), s(null), i(!1);
}, []);
return { createDoc: o, data: t, error: a, loading: l, reset: d };
}, be = (c) => {
const { db: r } = k(), [t, n] = y(null), [a, s] = y(!1), l = _(
async (o) => {
if (!c)
throw new Error("Doctype is required");
const d = { doctype: c, name: o };
s(!0), n(null);
try {
await r.deleteDoc(d);
} catch (p) {
const f = p instanceof Error ? p : new Error(String(p));
throw n(f), f;
} finally {
s(!1);
}
},
[r, c]
), i = _(() => {
n(null), s(!1);
}, []);
return { deleteDoc: l, error: t, loading: a, reset: i };
}, Te = () => {
const { file: c } = k(), [r, t] = y(null), [n, a] = y(null), [s, l] = y(!1), [i, o] = y(null), d = _(
async (f, h = {}) => {
const E = {
file: f,
is_private: !1,
...h
};
l(!0), a(null), o({ loaded: 0, total: f.size, percentage: 0 });
try {
const g = await c.upload(E);
return t(g), o({ loaded: f.size, total: f.size, percentage: 100 }), g;
} catch (g) {
const T = g instanceof Error ? g : new Error(String(g));
throw a(T), T;
} finally {
l(!1);
}
},
[c]
), p = _(() => {
t(null), a(null), l(!1), o(null);
}, []);
return { upload: d, data: r, error: n, loading: s, progress: i, reset: p };
}, _e = (c, r, t = {}) => {
const { db: n } = k(), a = c && r ? `${c}/${r}` : null, {
data: s,
error: l,
mutate: i,
isValidating: o,
isLoading: d
} = U(
a,
a ? async () => n.getDoc(c, r) : null,
{
revalidateIfStale: !0,
revalidateOnFocus: !1,
revalidateOnReconnect: !0,
...t
}
);
return {
data: s,
error: l,
mutate: i,
isValidating: o,
isLoading: d
};
}, Re = (c, r = {}) => {
const { db: t } = k(), n = c?.doctype ? JSON.stringify({ ...c, type: "count" }) : null, {
data: a,
error: s,
mutate: l,
isValidating: i,
isLoading: o
} = U(
n,
n ? async () => t.getDocCount(c) : null,
{
revalidateIfStale: !0,
revalidateOnFocus: !1,
revalidateOnReconnect: !0,
...r
}
);
return {
data: a || 0,
error: s,
mutate: l,
isValidating: i,
isLoading: o
};
}, ke = (c, r = {}) => {
const { db: t } = k(), n = c?.doctype ? JSON.stringify(c) : null, {
data: a,
error: s,
mutate: l,
isValidating: i,
isLoading: o
} = U(
n,
n ? async () => t.getDocList(c) : null,
{
revalidateIfStale: !0,
revalidateOnFocus: !1,
revalidateOnReconnect: !0,
...r
}
);
return {
data: a || [],
error: s,
mutate: l,
isValidating: i,
isLoading: o
};
}, Se = (c, r = {}, t = 300) => {
const { call: n } = k(), [a, s] = y([]), [l, i] = y(null), [o, d] = y(!1), [p, f] = y(""), h = _((g) => {
f(g);
}, []);
W(() => {
if (!p.trim() || !c) {
s([]);
return;
}
const g = setTimeout(async () => {
d(!0), i(null);
try {
const T = await n({
method: "frappe.desk.search.search_link",
args: {
doctype: c,
txt: p,
filters: r
}
});
s(T || []);
} catch (T) {
const x = T instanceof Error ? T : new Error(String(T));
i(x), s([]);
} finally {
d(!1);
}
}, t);
return () => clearTimeout(g);
}, [p, c, r, t, n]);
const E = _(() => {
s([]), i(null), d(!1), f("");
}, []);
return { search: h, data: a, error: l, loading: o, reset: E };
}, ve = (c) => {
const { db: r } = k(), [t, n] = y(null), [a, s] = y(null), [l, i] = y(!1), o = _(
async (p, f) => {
if (!c)
throw new Error("Doctype is required");
const h = { doctype: c, name: p, doc: f };
i(!0), s(null);
try {
const E = await r.updateDoc(h);
return n(E), E;
} catch (E) {
const g = E instanceof Error ? E : new Error(String(E));
throw s(g), g;
} finally {
i(!1);
}
},
[r, c]
), d = _(() => {
n(null), s(null), i(!1);
}, []);
return { updateDoc: o, data: t, error: a, loading: l, reset: d };
};
export {
pe as FrappeClient,
ge as FrappeProvider,
ye as useFrappeAuth,
Ee as useFrappeCall,
k as useFrappeContext,
we as useFrappeCreateDoc,
be as useFrappeDeleteDoc,
Te as useFrappeFileUpload,
_e as useFrappeGetDoc,
Re as useFrappeGetDocCount,
ke as useFrappeGetDocList,
Se as useFrappeSearch,
ve as useFrappeUpdateDoc
};