apiblaze 0.18.0 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -703,7 +703,7 @@ var import_commander = require("commander");
703
703
  var import_chalk39 = __toESM(require("chalk"));
704
704
 
705
705
  // package.json
706
- var version = "0.18.0";
706
+ var version = "0.18.2";
707
707
 
708
708
  // src/index.ts
709
709
  init_types();
@@ -78,6 +78,7 @@ var UsersGroupsWidget = React.forwardRef(function UsersGroupsWidget2({ endpoint
78
78
  const t = { ...DEFAULTS, ...theme ?? {} };
79
79
  const headerBg = t.headerBackground || t.surface;
80
80
  const [access, setAccess] = React.useState("ok");
81
+ const [myEmail, setMyEmail] = React.useState(null);
81
82
  const [groups, setGroups] = React.useState(null);
82
83
  const [users, setUsers] = React.useState([]);
83
84
  const [observed, setObserved] = React.useState([]);
@@ -106,6 +107,7 @@ var UsersGroupsWidget = React.forwardRef(function UsersGroupsWidget2({ endpoint
106
107
  try {
107
108
  const d = await call();
108
109
  setAccess(d.access === "pending" ? "pending" : "ok");
110
+ setMyEmail(d.email ?? null);
109
111
  setGroups((d.groups ?? []).slice().sort((a, b) => a.name.localeCompare(b.name)));
110
112
  setUsers(d.users ?? []);
111
113
  setObserved(d.observed ?? []);
@@ -211,10 +213,34 @@ var UsersGroupsWidget = React.forwardRef(function UsersGroupsWidget2({ endpoint
211
213
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { style: { fontSize: 15 }, children: title }),
212
214
  access === "ok" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: btn("primary", true), disabled: busy, onClick: () => setShowCreate((v) => !v), "aria-label": "Create a new group", children: "+ New group" })
213
215
  ] }),
214
- access === "pending" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "28px 20px", textAlign: "center", color: t.muted }, children: [
215
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 600, color: t.text, marginBottom: 6 }, children: "Admin access pending" }),
216
- "You don\u2019t have group-management access for this workspace yet. If you were just added as an admin, it activates on your first sign-in \u2014 try refreshing. Otherwise ask your API provider to add your email as a workspace admin.",
217
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: btn("ghost", true), onClick: load, children: "Refresh" }) })
216
+ access === "pending" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "28px 20px", textAlign: "center", color: t.muted, lineHeight: 1.5 }, children: [
217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 700, color: t.text, marginBottom: 6, fontSize: 15 }, children: "Admin access required" }),
218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: 12 }, children: [
219
+ "Managing users & groups is limited to ",
220
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "workspace admins" }),
221
+ ". You\u2019re signed in",
222
+ myEmail ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
223
+ " as ",
224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { style: { fontFamily: t.monoFontFamily }, children: myEmail })
225
+ ] }) : "",
226
+ ", but this account isn\u2019t an admin yet."
227
+ ] }),
228
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", { style: { textAlign: "left", maxWidth: 420, margin: "0 auto 12px", paddingLeft: 18 }, children: [
229
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
230
+ "If your API provider just made you an admin, it activates the first time you open this \u2014 ",
231
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Refresh" }),
232
+ "."
233
+ ] }),
234
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
235
+ "Otherwise, ask your API provider to add",
236
+ myEmail ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
237
+ " ",
238
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { style: { fontFamily: t.monoFontFamily }, children: myEmail })
239
+ ] }) : " your email",
240
+ " to the workspace\u2019s admin list."
241
+ ] })
242
+ ] }),
243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: btn("ghost", true), onClick: load, children: "Refresh" })
218
244
  ] }),
219
245
  access === "ok" && showCreate && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, padding: "12px 16px", borderBottom: `1px solid ${t.border}` }, children: [
220
246
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -43,6 +43,7 @@ var UsersGroupsWidget = React.forwardRef(function UsersGroupsWidget2({ endpoint
43
43
  const t = { ...DEFAULTS, ...theme ?? {} };
44
44
  const headerBg = t.headerBackground || t.surface;
45
45
  const [access, setAccess] = React.useState("ok");
46
+ const [myEmail, setMyEmail] = React.useState(null);
46
47
  const [groups, setGroups] = React.useState(null);
47
48
  const [users, setUsers] = React.useState([]);
48
49
  const [observed, setObserved] = React.useState([]);
@@ -71,6 +72,7 @@ var UsersGroupsWidget = React.forwardRef(function UsersGroupsWidget2({ endpoint
71
72
  try {
72
73
  const d = await call();
73
74
  setAccess(d.access === "pending" ? "pending" : "ok");
75
+ setMyEmail(d.email ?? null);
74
76
  setGroups((d.groups ?? []).slice().sort((a, b) => a.name.localeCompare(b.name)));
75
77
  setUsers(d.users ?? []);
76
78
  setObserved(d.observed ?? []);
@@ -176,10 +178,34 @@ var UsersGroupsWidget = React.forwardRef(function UsersGroupsWidget2({ endpoint
176
178
  /* @__PURE__ */ jsx("strong", { style: { fontSize: 15 }, children: title }),
177
179
  access === "ok" && /* @__PURE__ */ jsx("button", { style: btn("primary", true), disabled: busy, onClick: () => setShowCreate((v) => !v), "aria-label": "Create a new group", children: "+ New group" })
178
180
  ] }),
179
- access === "pending" && /* @__PURE__ */ jsxs("div", { style: { padding: "28px 20px", textAlign: "center", color: t.muted }, children: [
180
- /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, color: t.text, marginBottom: 6 }, children: "Admin access pending" }),
181
- "You don\u2019t have group-management access for this workspace yet. If you were just added as an admin, it activates on your first sign-in \u2014 try refreshing. Otherwise ask your API provider to add your email as a workspace admin.",
182
- /* @__PURE__ */ jsx("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ jsx("button", { style: btn("ghost", true), onClick: load, children: "Refresh" }) })
181
+ access === "pending" && /* @__PURE__ */ jsxs("div", { style: { padding: "28px 20px", textAlign: "center", color: t.muted, lineHeight: 1.5 }, children: [
182
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 700, color: t.text, marginBottom: 6, fontSize: 15 }, children: "Admin access required" }),
183
+ /* @__PURE__ */ jsxs("div", { style: { marginBottom: 12 }, children: [
184
+ "Managing users & groups is limited to ",
185
+ /* @__PURE__ */ jsx("strong", { children: "workspace admins" }),
186
+ ". You\u2019re signed in",
187
+ myEmail ? /* @__PURE__ */ jsxs(Fragment, { children: [
188
+ " as ",
189
+ /* @__PURE__ */ jsx("code", { style: { fontFamily: t.monoFontFamily }, children: myEmail })
190
+ ] }) : "",
191
+ ", but this account isn\u2019t an admin yet."
192
+ ] }),
193
+ /* @__PURE__ */ jsxs("ul", { style: { textAlign: "left", maxWidth: 420, margin: "0 auto 12px", paddingLeft: 18 }, children: [
194
+ /* @__PURE__ */ jsxs("li", { children: [
195
+ "If your API provider just made you an admin, it activates the first time you open this \u2014 ",
196
+ /* @__PURE__ */ jsx("strong", { children: "Refresh" }),
197
+ "."
198
+ ] }),
199
+ /* @__PURE__ */ jsxs("li", { children: [
200
+ "Otherwise, ask your API provider to add",
201
+ myEmail ? /* @__PURE__ */ jsxs(Fragment, { children: [
202
+ " ",
203
+ /* @__PURE__ */ jsx("code", { style: { fontFamily: t.monoFontFamily }, children: myEmail })
204
+ ] }) : " your email",
205
+ " to the workspace\u2019s admin list."
206
+ ] })
207
+ ] }),
208
+ /* @__PURE__ */ jsx("button", { style: btn("ghost", true), onClick: load, children: "Refresh" })
183
209
  ] }),
184
210
  access === "ok" && showCreate && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, padding: "12px 16px", borderBottom: `1px solid ${t.border}` }, children: [
185
211
  /* @__PURE__ */ jsx(
@@ -54,7 +54,6 @@ function createPlaneCore(cfg) {
54
54
  function planeFetch(base, method, path, user, opts = {}) {
55
55
  const params = new URLSearchParams({ product: "apiblaze", ...opts.query ?? {} });
56
56
  const headers = { "X-API-Key": cfg.cpKey, "X-End-User-Id": user.userId };
57
- if (user.email) headers["X-End-User-Email"] = String(user.email);
58
57
  let body;
59
58
  if (opts.body !== void 0) {
60
59
  headers["Content-Type"] = "application/json";
@@ -108,7 +107,7 @@ function createApiblazeGroups(cfg) {
108
107
  iam("GET", "/users", user, tenant),
109
108
  iam("GET", "/observed-identities", user, tenant)
110
109
  ]);
111
- if (groupsRes.status === 403) return { status: 200, data: { access: "pending", groups: [], users: [], observed: [] } };
110
+ if (groupsRes.status === 403) return { status: 200, data: { access: "pending", email: user.email ?? null, groups: [], users: [], observed: [] } };
112
111
  if (!groupsRes.ok) return { status: groupsRes.status, data: { error: await safeErr(groupsRes) } };
113
112
  const g = await groupsRes.json();
114
113
  const u = usersRes.ok ? await usersRes.json() : { users: [] };
@@ -206,6 +205,7 @@ function createApiblazeKeys(cfg) {
206
205
  const expiresIn = cfg.keyExpiresInSeconds;
207
206
  const planeFetch = (method, path, user, opts = {}) => core.planeFetch(base, method, path, user, opts);
208
207
  const resolveTenant = (user) => core.resolveTenant(user);
208
+ const ensureEndUser = (user, tenant) => core.ensureEndUser(user, tenant);
209
209
  async function allowedTypesFor(user) {
210
210
  const raw = cfg.resolveKeyTypes ? await cfg.resolveKeyTypes(user) : user.keyTypes;
211
211
  if (raw === false) return false;
@@ -242,6 +242,7 @@ function createApiblazeKeys(cfg) {
242
242
  return { status: 403, data: { error: "You are not allowed to create that key type." } };
243
243
  }
244
244
  const chosen = op.keyType ?? (eligible.includes("call-only") ? "call-only" : eligible[0]);
245
+ await ensureEndUser(user, tenant2);
245
246
  const body = { tenant: tenant2, key_type_ids: [chosen], environment: "prod" };
246
247
  if (typeof expiresIn === "number" && expiresIn > 0) body.expires_in_seconds = expiresIn;
247
248
  const r = await planeFetch("POST", "/apikeys", user, { body });
@@ -26,7 +26,6 @@ function createPlaneCore(cfg) {
26
26
  function planeFetch(base, method, path, user, opts = {}) {
27
27
  const params = new URLSearchParams({ product: "apiblaze", ...opts.query ?? {} });
28
28
  const headers = { "X-API-Key": cfg.cpKey, "X-End-User-Id": user.userId };
29
- if (user.email) headers["X-End-User-Email"] = String(user.email);
30
29
  let body;
31
30
  if (opts.body !== void 0) {
32
31
  headers["Content-Type"] = "application/json";
@@ -80,7 +79,7 @@ function createApiblazeGroups(cfg) {
80
79
  iam("GET", "/users", user, tenant),
81
80
  iam("GET", "/observed-identities", user, tenant)
82
81
  ]);
83
- if (groupsRes.status === 403) return { status: 200, data: { access: "pending", groups: [], users: [], observed: [] } };
82
+ if (groupsRes.status === 403) return { status: 200, data: { access: "pending", email: user.email ?? null, groups: [], users: [], observed: [] } };
84
83
  if (!groupsRes.ok) return { status: groupsRes.status, data: { error: await safeErr(groupsRes) } };
85
84
  const g = await groupsRes.json();
86
85
  const u = usersRes.ok ? await usersRes.json() : { users: [] };
@@ -178,6 +177,7 @@ function createApiblazeKeys(cfg) {
178
177
  const expiresIn = cfg.keyExpiresInSeconds;
179
178
  const planeFetch = (method, path, user, opts = {}) => core.planeFetch(base, method, path, user, opts);
180
179
  const resolveTenant = (user) => core.resolveTenant(user);
180
+ const ensureEndUser = (user, tenant) => core.ensureEndUser(user, tenant);
181
181
  async function allowedTypesFor(user) {
182
182
  const raw = cfg.resolveKeyTypes ? await cfg.resolveKeyTypes(user) : user.keyTypes;
183
183
  if (raw === false) return false;
@@ -214,6 +214,7 @@ function createApiblazeKeys(cfg) {
214
214
  return { status: 403, data: { error: "You are not allowed to create that key type." } };
215
215
  }
216
216
  const chosen = op.keyType ?? (eligible.includes("call-only") ? "call-only" : eligible[0]);
217
+ await ensureEndUser(user, tenant2);
217
218
  const body = { tenant: tenant2, key_type_ids: [chosen], environment: "prod" };
218
219
  if (typeof expiresIn === "number" && expiresIn > 0) body.expires_in_seconds = expiresIn;
219
220
  const r = await planeFetch("POST", "/apikeys", user, { body });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "description": "APIblaze CLI — Chat with your APIs, Manage your API keys, users and groups with the APIblaze serverless proxy",
5
5
  "keywords": [
6
6
  "apiblaze",