@scalar/api-client
Version:
the open source API testing client
283 lines (282 loc) • 8.53 kB
JavaScript
import { collectionSchema as M, requestSchema as O, serverSchema as V, tagSchema as S, securitySchemeSchema as Z, createExampleFromRequest as x } from "@scalar/oas-utils/entities/spec";
import { schemaModel as v, isHttpMethod as k } from "@scalar/oas-utils/helpers";
import { getNestedValue as D } from "@scalar/object-utils/nested";
import H from "microdiff";
import { z as i } from "zod";
const j = (e, s = []) => {
const t = [];
let a = !1;
for (let r = 0; r < e.length; r++) {
if (a) {
a = !1;
continue;
}
const n = e[r], u = e[r + 1];
if (n) {
if (s.length)
n.path = [...s, ...n.path], u && (u.path = [...s, ...u.path]);
else if (n.path[0] !== "paths") {
t.push(n);
continue;
}
if (n.type === "REMOVE" && u?.type === "CREATE") {
const [, l, p] = n.path, [, o, h] = u.path, c = ["paths", o].filter((f) => typeof f == "string");
if (l !== o && t.push({
type: "CHANGE",
path: ["paths", "path"],
oldValue: l,
value: o
}), p && typeof h == "string" && p !== h && o && (t.push({
type: "CHANGE",
path: ["paths", o, "method"],
oldValue: p,
value: h
}), c.push(h)), s.length === 0) {
const f = H(n.oldValue, u.value);
if (f.length) {
const R = j(f, c);
t.push(...R);
}
}
a = !0;
} else n.type === "CREATE" && n.path.length > 3 && typeof n.path.at(-1) != "number" ? t.push({ ...n, type: "CHANGE", oldValue: void 0 }) : n.type === "REMOVE" && n.path.length > 3 && typeof n.path.at(-1) != "number" ? t.push({ ...n, type: "CHANGE", value: void 0 }) : t.push(n);
}
}
return t;
}, E = (e, s, t) => {
for (const a of e) {
const r = s[a];
if (r && t(r))
return r;
}
return null;
}, y = (e) => e instanceof i.ZodOptional ? y(e.unwrap()) : e instanceof i.ZodDefault ? y(e._def.innerType) : e instanceof i.ZodEffects ? y(e._def.schema) : e instanceof i.ZodCatch ? y(e._def.innerType) : e, G = (e, s) => {
let t = e;
for (const a of s) {
if (t = y(t), t instanceof i.ZodAny)
return t;
if (t instanceof i.ZodObject && typeof a == "string" && a in t.shape)
t = t.shape[a];
else if (t instanceof i.ZodArray)
if (typeof a == "number")
t = t.element;
else if (typeof a == "string")
if (t = t.element, t instanceof i.ZodObject && a in t.shape)
t = t.shape[a];
else
return null;
else
return null;
else if (t instanceof i.ZodRecord)
t = t.valueSchema;
else
return null;
t = y(t);
}
return t;
}, d = (e, s) => {
const t = G(e, s.path);
if (!t)
return null;
const a = s.path.join("."), r = s.path.slice(0, -1).join(".");
if (s.type === "REMOVE")
return {
path: a,
pathMinusOne: r,
value: void 0
};
const n = v(s.value, t, !1);
return typeof n > "u" || n === null ? null : {
path: a,
pathMinusOne: r,
value: n
};
}, L = (e, { activeCollection: s }, { collectionMutators: t }) => {
if (!s.value)
return !1;
if (typeof e.path[e.path.length - 1] == "number" && (e.type === "CREATE" || e.type === "REMOVE")) {
const a = d(M, {
...e,
path: e.path
});
if (!a)
return !1;
const r = [...D(s.value, a.pathMinusOne)];
e.type === "CREATE" ? r.push(a.value) : e.type === "REMOVE" && r.pop(), t.edit(s.value.uid, a.pathMinusOne, r);
} else {
const a = d(M, e);
if (!a)
return !1;
t.edit(s.value.uid, a.path, a.value);
}
return !0;
}, T = (e, s) => {
const { requests: t, requestExamples: a, requestExampleMutators: r } = s, n = t[e];
n?.examples.forEach((u) => {
const l = x(n, a[u]?.name ?? "Default");
l && r.set({
...l,
uid: u
});
});
}, P = (e, { activeCollection: s }, t) => {
if (!s.value)
return !1;
const { requests: a, requestMutators: r } = t, [, n, u, ...l] = e.path;
if (n === "path" && e.type === "CHANGE")
s.value.requests.forEach((p) => {
a[p]?.path === e.oldValue && r.edit(p, "path", e.value);
});
else if (u === "method" && e.type === "CHANGE")
s.value.requests.forEach((p) => {
a[p]?.method === e.oldValue && a[p]?.path === n && r.edit(p, "method", e.value);
});
else if (e.type !== "CHANGE" && typeof l.at(-1) == "number") {
const p = E(
s.value.requests,
a,
(c) => c.path === n && c.method === u
), o = d(O, {
...e,
path: e.path.slice(3)
});
if (!p || !o)
return !1;
const h = [...D(p, o.pathMinusOne)];
e.type === "CREATE" ? h.push(o.value) : e.type === "REMOVE" && h.pop(), r.edit(p.uid, o.pathMinusOne, h), (e.path[3] === "parameters" || e.path[3] === "requestBody") && T(p.uid, t);
} else if (e.type === "CREATE") {
const [p] = Object.entries(e.value ?? {}), [o, h] = p ?? [], c = u ? e.value : h, f = u || o, R = V.array().parse(c.servers ?? []), { security: q, ...N } = c, A = {
...N,
method: k(f) ? f : "get",
path: n,
parameters: c.parameters ?? [],
servers: R.map((m) => m.uid)
};
q?.length && (A.security = q.map((m) => {
if (Object.keys(m).length) {
const [g] = Object.keys(m);
return g ? {
[g]: m[g]
} : m;
}
return m;
}));
const b = v(A, O, !1);
if (!b)
return !1;
r.add(b, s.value.uid);
} else if (e.type === "REMOVE") {
const p = E(
s.value.requests,
a,
(o) => o.path === n && o.method === u
);
if (!p)
return !1;
r.delete(p, s.value.uid);
} else if (e.type === "CHANGE") {
const p = E(
s.value.requests,
a,
(h) => h.path === n && h.method === u
), o = d(O, { ...e, path: l });
if (!p || !o)
return !1;
r.edit(p.uid, o.path, o.value), (e.path[3] === "parameters" || e.path[3] === "requestBody") && T(p.uid, t);
}
return !0;
}, W = (e, { activeCollection: s }, { servers: t, serverMutators: a }) => {
if (!s.value)
return !1;
const [, r, ...n] = e.path;
if (n?.length) {
const u = s.value.servers[r];
if (!u)
return !1;
const l = t[u], p = d(V, { ...e, path: n });
if (!l || !p)
return !1;
const h = e.type === "REMOVE" && n[n.length - 1] === "variables" ? {} : p.value;
a.edit(u, p.path, h);
} else if (e.type === "REMOVE") {
if (!s.value.servers[r])
return !1;
a.delete(s.value.servers[r], s.value.uid);
} else if (e.type === "CREATE") {
const u = v(e.value, V, !1);
if (!u)
return !1;
a.add(u, s.value.uid);
}
return !0;
}, I = (e, { activeCollection: s }, { tags: t, tagMutators: a }) => {
if (!s.value)
return !1;
const [, r, ...n] = e.path;
if (n?.length) {
const u = s.value.tags[r];
if (!u)
return !1;
const l = t[u], p = d(S, { ...e, path: n });
if (!l || !p)
return !1;
a.edit(u, p.path, p.value);
} else if (e.type === "REMOVE") {
const u = s.value.tags[r];
if (!u)
return !1;
const l = t[u];
if (!l)
return !1;
a.delete(l, s.value.uid);
} else if (e.type === "CREATE") {
const u = v(e.value, S, !1);
if (!u)
return !1;
a.add(u, s.value.uid);
}
return !0;
}, _ = (e, s, t) => {
const a = y(e);
if (a instanceof i.ZodUnion || a instanceof i.ZodDiscriminatedUnion) {
for (const r of a.options)
if (r instanceof i.ZodObject && s in r.shape && r.shape[s] instanceof i.ZodLiteral && r.shape[s].value === t)
return r;
}
return null;
}, J = (e, { activeCollection: s }, { securitySchemes: t, securitySchemeMutators: a }) => {
if (!s.value)
return !1;
const [, , r, ...n] = e.path, u = t[r] ?? E(
s.value.securitySchemes,
t,
(l) => l.nameKey === r
);
if (n?.length) {
const l = _(Z, "type", u?.type ?? "");
if (!l || !u)
return !1;
const p = d(l, { ...e, path: n });
if (!p)
return !1;
const o = p.path;
a.edit(u.uid, o, p.value);
} else if (e.type === "REMOVE") {
if (!u)
return !1;
a.delete(u.uid);
} else e.type === "CREATE" && a.add(Z.parse(e.value), s.value.uid);
return !0;
};
export {
j as combineRenameDiffs,
E as findResource,
L as mutateCollectionDiff,
P as mutateRequestDiff,
J as mutateSecuritySchemeDiff,
W as mutateServerDiff,
I as mutateTagDiff,
_ as narrowUnionSchema,
d as parseDiff,
G as traverseZodSchema
};