UNPKG

azion

Version:

Azion Packages for Edge Computing.

510 lines (509 loc) 14.5 kB
const y = (r, t) => r?.length > t ? r.slice(0, t) : r; async function m(r, t, s, o = !0) { const e = await fetch(r, t); if (!e.ok) try { const n = await e.json(); if (s && console.log("Error response body:", n), n.errors && Array.isArray(n.errors) && n.errors.length > 0 || n.detail || n.message) return n; const a = `HTTP error! Status: ${e.status} - ${e.statusText}`; throw s && console.log(`Error in fetch: ${a}`), new Error(a); } catch { const n = `HTTP error! Status: ${e.status} - ${e.statusText}`; throw s && console.log(`Error in fetch: ${n}`), new Error(n); } if (o) { const n = e.headers.get("content-type"); if (!n || !n.includes("application/json")) { const i = `Expected JSON response, but got: ${await e.text()}`; throw s && console.log(`Error in fetch: ${i}`), new Error(i); } return await e.json(); } else return await e.text(); } const h = (r = "production") => ({ production: "https://api.azion.com/v4/workspace/sql/databases", development: "/v4/workspace/sql/databases", staging: "https://stage-api.azion.com/v4/workspace/sql/databases" })[r], w = (r, t = {}) => { const s = { Accept: "application/json", ...t }; return r ? { ...s, Authorization: `Token ${r}` } : s; }, E = (r, t, s) => { const o = { method: r, headers: t, credentials: "include" }; return s && (o.body = s), o; }, D = (r, t, s) => { let o = { message: "Error unknown", operation: s }; if (t.errors && Array.isArray(t.errors) && t.errors.length > 0) { const e = t.errors[0]; if (e.detail) return o = { message: e.detail, operation: s }, o; if (e.title) return o = { message: e.title, operation: s }, o; } return r.forEach((e) => { t[e] && (o = { message: Array.isArray(t[e]) ? t[e].join(", ") : t[e], operation: s }); }), o; }, Q = async (r, t, s, o = "production") => { try { const e = h(o), n = w(r, { "Content-Type": "application/json" }), a = E("POST", n, JSON.stringify({ name: t })), c = await m(e, a, s); if (c.errors) return { error: D([], c, "post database") }; const i = c.data; return s && console.log("Response Post Database", JSON.stringify(c)), { state: c.state, data: i }; } catch (e) { return s && console.error("Error creating EdgeDB:", e), { error: { message: e.message, operation: "post database" } }; } }, z = async (r, t, s, o = "production") => { try { const e = h(o), n = w(r), a = E("DELETE", n), c = await m(`${e}/${t}`, a, s); return c.errors ? { error: D([], c, "delete database") } : c; } catch (e) { return s && console.error("Error deleting EdgeDB:", e), { error: { message: e.toString(), operation: "delete database" } }; } }, W = async (r, t, s, o, e = "production") => { try { const n = h(e), a = w(r, { "Content-Type": "application/json" }), c = E("POST", a, JSON.stringify({ statements: s })), i = await m(`${n}/${t}/query`, c, o); if (i.errors) return { error: D([], i, "post query") }; const d = i.data; if (o) { const p = { ...i, data: i?.data?.map((u) => ({ ...u, results: { ...u.results, rows: y(u.results?.rows, 10) } })) }; console.log("Response Query:", JSON.stringify(p)); } return { state: i.state, data: d }; } catch (n) { return o && console.error("Error querying EdgeDB:", n), { error: { message: n.toString(), operation: "post query" } }; } }, A = async (r, t, s, o = "production") => { try { const e = h(o), n = new URL(e); t && Object.entries(t).forEach(([p, u]) => { u !== void 0 && n.searchParams.append(p, u.toString()); }); const a = w(r), c = E("GET", a), i = await m(n.toString(), c, s); if (i.errors) return { error: D([], i, "get databases") }; const d = i.results; if (s) { const p = { ...i, results: y(i.results, 10) }; console.log("Response Databases:", JSON.stringify(p)); } return { count: i.count, results: d }; } catch (e) { return s && console.error("Error getting all EdgeDBs:", e), { error: { message: e.message, operation: "get databases" } }; } }, R = ({ state: r, results: t }) => { let s = []; if (t instanceof Array) { if (t.length === 0) return { results: [] }; let o = null; s = t?.map((e) => (e?.rows && (o = e.rows.map((n) => { const a = {}; return e?.columns && e.columns.forEach((c, i) => { a[c] = n[i]; }), a; })), { statement: e.statement, rows: o })); } return { state: r, results: s }; }, T = () => globalThis.Azion?.Sql || null; class J { database = null; constructor() { this.database = T()?.Database || null; } /** * Maps query results to a structured format. * @param {Array<{ statement: string; result: Azion.Sql.Rows }>} resultRows - The result rows from the query. * @returns {Promise<Array<QueryResult | NonSelectQueryResult>>} The mapped query results. */ mapperQuery = async (t) => { const s = []; for (const o of t) { const e = o.result.columnCount(); if (e === 0) continue; const n = []; for (let i = 0; i < e; i++) n.push(o.result.columnName(i)); let a = await o.result.next(); const c = []; for (; a; ) { const i = []; for (let d = 0; d < e; d++) i.push(a.getValue(d)); c.push(i), a = await o.result.next(); } s.push({ statement: o?.statement?.split(" ")[0], // TODO: This can improve columns: n, rows: c }); } return Promise.resolve(s); }; /** * Executes a series of SQL statements on the specified database. * @param {string} name - The name of the database. * @param {string[]} statements - The SQL statements to execute. * @param {AzionClientOptions} [options] - Optional client options. * @returns {Promise<Array<{ statement: string; result: Azion.Sql.Rows }>>} The results of the executed statements. */ query = async (t, s, o) => { if (this.database?.open) { const e = await this.database?.open(t), n = s.map(async (a) => { const c = await e?.query(a); return { statement: a, result: c }; }); try { const a = await Promise.all(n); if (a.every((c) => c.result?.columnCount() > 0)) return a; } catch (a) { throw o?.debug && console.error("Error querying:", a?.message), a; } } return []; }; } const q = async (r, t, s, o) => { const e = await A(r, { search: t, page_size: 1 }, o?.debug, o?.env); if (e?.error) return { error: e.error }; const n = e?.results?.[0]; if (!n?.name) return { error: { message: `Database ${t} not found`, operation: "apiQuery" } }; const { state: a, data: c, error: i } = await W(r, n.id, s, o?.debug, o?.env); if (i) return { error: { message: i.message || "Error executing query", operation: "apiQuery" } }; const d = c?.map((u, f) => ({ statement: s[f]?.split(" ")[0], columns: u?.results?.columns && u?.results?.columns.length > 0 ? u?.results?.columns : void 0, rows: u?.results?.rows && u?.results?.rows.length > 0 ? u?.results?.rows : void 0, error: u?.error || void 0 })); if (o?.debug && d) { const u = d.map((f) => ({ ...f, rows: y(f?.rows || [], 10) })); console.log( "Response Query:", JSON.stringify({ state: a, results: u, toObject: () => null }) ); } const p = d && d.filter((u) => u?.error !== void 0); return { data: { state: a, results: d, toObject: () => R({ results: d, state: a }) }, // If there are, return an error response error: p && p.length > 0 ? { message: p.map((u) => u?.error || "Error executing query").join(", "), operation: "apiQuery" } : void 0 }; }, N = async (r, t, s, o) => { try { const e = new J(), n = await e.query(t, s, o), a = { state: "executed-runtime", results: [], toObject: () => null }, c = await e.mapperQuery(n); if (c && c.length > 0 && (a.state = "executed-runtime", a.results = c), o?.debug) { const i = { ...a, results: a.results.map((d) => ({ ...d, rows: y(d?.rows || [], 10) })) }; console.log("Response Query:", JSON.stringify(i)); } return { data: { ...a, toObject: () => R(a) } }; } catch (e) { return { error: { message: e?.message || "Error executing query", operation: "executing query" } }; } }; function $(r, t) { return console.error("An unexpected error occurred:", r), { error: { message: "An unexpected error occurred during the operation", operation: t } }; } const x = () => typeof window < "u" && typeof window.document < "u", _ = !x() && process?.env.AZION_DEBUG === "true", l = (r) => x() ? r ?? "" : r ?? process?.env.AZION_TOKEN ?? "", j = (r) => r ?? !!_, B = (r) => x() ? r ?? "production" : r ?? process?.env.AZION_ENV ?? "production", g = (r) => ({ ...r, debug: j(r?.debug), env: B(r?.env) }), O = { parse: (r) => ({ id: r.id, name: r.name, status: r.status, active: r.active, lastModified: r.last_modified, lastEditor: r.last_editor, productVersion: r.product_version }) }, P = async (r, t, s) => { try { const o = g(s), e = await Q(l(r), t, o.debug, o.env); if (e.data) { const n = O.parse(e.data); return { data: { state: e.state ?? "executed", ...n, query: (a) => b(l(r), t, a, o), execute: (a) => v(l(r), t, a, o), getTables: (a) => S(t, { ...a, debug: o.debug }) } }; } return { error: e.error }; } catch (o) { return $(o, "create database"); } }, U = async (r, t, s) => { const o = g(s), e = await z(l(r), t, o.debug, o.env); return e?.state ? { data: { state: e.state ?? "executed" } } : { error: e.error }; }, C = async (r, t, s) => { try { const o = g(s), e = await A( l(r), { search: t, page_size: 1 }, o.debug, o.env ); if (e.results && e.results.length > 0) { const n = e.results.filter((c) => c.name === t); return n.length === 0 ? { error: { message: `Database ${t} not found`, operation: "get database" } } : { data: { ...O.parse(n[0]), query: (c) => b(l(r), t, c, o), execute: (c) => v(l(r), t, c, o), getTables: (c) => S(t, { ...c, debug: o.debug }) } }; } return { error: e.error }; } catch (o) { return $(o, "get database"); } }, M = async (r, t, s) => { const o = g(s), e = await A(l(r), t, o.debug, o.env); return e.error ? { error: e.error } : !e?.results || e?.results?.length === 0 ? { data: { count: e.count ?? 0, databases: [] } } : { data: { count: e.count ?? 0, databases: e.results.map((n) => ({ ...O.parse(n), query: (a) => b(l(r), n.name, a, o), execute: (a) => v(l(r), n.name, a, o), getTables: (a) => S(n.name, { ...a, debug: o.debug }) })) } }; }, b = async (r, t, s, o) => { const e = g(o); if (!t || t === "") return { error: { message: "Database name is required", operation: "query database" } }; if (e.debug && console.log(`Executing statements on database ${t}: ${s}`), !Array.isArray(s) || s.length === 0) return { error: { message: 'No statements to execute. Please provide at least one statement. e.g ["SELECT * FROM users"]', operation: "query database" } }; if (!s.some( (a) => ["SELECT", "PRAGMA"].some((c) => a.trim().toUpperCase().startsWith(c)) )) throw new Error("Only read statements are allowed"); return e.external || !T() ? q(r, t, s, e) : N(r, t, s, e); }, v = async (r, t, s, o) => { const e = g(o); if (e.debug && console.log(`Executing statements on database ${t}: ${s}`), !t || t === "") return { error: { message: "Database name is required", operation: "execute database" } }; if (!Array.isArray(s) || s.length === 0) return { error: { message: `No statements to execute. Please provide at least one statement. e.g ["INSERT INTO users (name) VALUES ('John')"]`, operation: "execute database" } }; const n = s.some( (c) => ["INSERT", "UPDATE", "DELETE"].some((i) => c.trim().toUpperCase().startsWith(i)) ), a = s.some( (c) => c.toUpperCase().match(/^(CREATE|DROP|ALTER|ATTACH|VACUUM|PRAGMA)/) ); return !a && !n ? { error: { message: "Only write statements are allowed", operation: "execute database" } } : a && e.force === !1 ? { error: { message: "To admin statements, you need to set the force option to true", operation: "execute database" } } : e.external || !T() ? q(r, t, s, e) : N(r, t, s, e); }, I = async (r, t) => P(l(), r, t), L = (r, t) => U(l(), r, t), V = async (r, t) => C(l(), r, t), H = (r, t) => M(l(), r, t), S = async (r, t) => { const s = g(t); return b(l(), r, ["PRAGMA table_list"], s); }, G = (r, t, s) => b(l(), r, t, s), F = async (r, t, s) => v(l(), r, t, s), Z = (r) => { const t = l(r?.token), s = j(r?.options?.debug); return { createDatabase: (e) => P(t, e, { ...r?.options, debug: s }), deleteDatabase: (e) => U(t, e, { ...r?.options, debug: s }), getDatabase: (e) => C(t, e, { ...r?.options, debug: s }), getDatabases: (e) => M(t, e, { ...r?.options, debug: s }) }; }; export { Z as createClient, I as createDatabase, Z as default, L as deleteDatabase, V as getDatabase, H as getDatabases, S as getTables, F as useExecute, G as useQuery };