@ai-matrx/vault 0.1.27 → 0.1.28
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/CHANGELOG.md +8 -0
- package/dist/index.cjs +151 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +151 -21
- package/dist/index.js.map +1 -1
- package/dist/io/bitwarden-json.worker.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -1420,7 +1420,7 @@ interface ApiVaultPortOptions {
|
|
|
1420
1420
|
/** The host's `supabase.auth`: turns on approving a browser with a passkey. */
|
|
1421
1421
|
passkeys?: PasskeyAuthLike;
|
|
1422
1422
|
}
|
|
1423
|
-
declare function createApiVaultPort(
|
|
1423
|
+
declare function createApiVaultPort(hostApi: Api, options?: ApiVaultPortOptions): VaultPort;
|
|
1424
1424
|
|
|
1425
1425
|
/**
|
|
1426
1426
|
* Wrap any call that shows, copies or exports a secret. When the server answers "sign in again",
|
package/dist/index.d.ts
CHANGED
|
@@ -1420,7 +1420,7 @@ interface ApiVaultPortOptions {
|
|
|
1420
1420
|
/** The host's `supabase.auth`: turns on approving a browser with a passkey. */
|
|
1421
1421
|
passkeys?: PasskeyAuthLike;
|
|
1422
1422
|
}
|
|
1423
|
-
declare function createApiVaultPort(
|
|
1423
|
+
declare function createApiVaultPort(hostApi: Api, options?: ApiVaultPortOptions): VaultPort;
|
|
1424
1424
|
|
|
1425
1425
|
/**
|
|
1426
1426
|
* Wrap any call that shows, copies or exports a secret. When the server answers "sign in again",
|
package/dist/index.js
CHANGED
|
@@ -2637,9 +2637,12 @@ function normalizeLoginUrl(input) {
|
|
|
2637
2637
|
return null;
|
|
2638
2638
|
}
|
|
2639
2639
|
}
|
|
2640
|
+
function normalizeLoginUrls(inputs) {
|
|
2641
|
+
return inputs.map((u) => u.trim()).filter(Boolean).map((u) => normalizeLoginUrl(u) ?? u);
|
|
2642
|
+
}
|
|
2640
2643
|
function describeDestination(r) {
|
|
2641
2644
|
if (r.state === "reachable") return { url: r.normalizedUrl, state: r.state, tone: "success", message: "Website confirmed" };
|
|
2642
|
-
if (r.state === "invalid") return { url: r.normalizedUrl, state: r.state, tone: "
|
|
2645
|
+
if (r.state === "invalid") return { url: r.normalizedUrl, state: r.state, tone: "warning", message: "Not a public website. You can still save it." };
|
|
2643
2646
|
if (r.state === "not_found") return { url: r.normalizedUrl, state: r.state, tone: "warning", message: "Site answered, but this page was not found" };
|
|
2644
2647
|
return { url: r.normalizedUrl, state: r.state, tone: "warning", message: "Couldn\u2019t confirm it. You can still save it." };
|
|
2645
2648
|
}
|
|
@@ -5345,6 +5348,40 @@ function AssignResult({ sent, onAnother, onDone }) {
|
|
|
5345
5348
|
] });
|
|
5346
5349
|
}
|
|
5347
5350
|
|
|
5351
|
+
// src/lists/turn-back-on.ts
|
|
5352
|
+
async function turnBackOn(port, item, fields, options = {}) {
|
|
5353
|
+
const run = options.run ?? ((op) => op());
|
|
5354
|
+
const done = [];
|
|
5355
|
+
if (item.turnedOff) {
|
|
5356
|
+
await run(() => port.fields.updateItem(item, { active: true }));
|
|
5357
|
+
done.push("the item");
|
|
5358
|
+
}
|
|
5359
|
+
let n = 0;
|
|
5360
|
+
for (const f of fields) {
|
|
5361
|
+
if (f.active) continue;
|
|
5362
|
+
await run(() => port.fields.updateField(item, f.id, { active: true }));
|
|
5363
|
+
n += 1;
|
|
5364
|
+
}
|
|
5365
|
+
if (n) done.push(n === 1 ? "1 field" : `${n} fields`);
|
|
5366
|
+
if (fields.some((f) => f.key === OTP_SEED_KEY)) {
|
|
5367
|
+
const codes = await port.authenticator.get(item);
|
|
5368
|
+
if (codes && !codes.enabled) {
|
|
5369
|
+
await run(() => port.authenticator.setEnabled(item, true));
|
|
5370
|
+
done.push("one-time codes");
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
if (options.browserFill && !item.browserFillEnabled && item.loginUrls.length > 0) {
|
|
5374
|
+
await run(() => port.fields.updateItem(item, { browserFillEnabled: true }));
|
|
5375
|
+
done.push("browser fill");
|
|
5376
|
+
}
|
|
5377
|
+
return done;
|
|
5378
|
+
}
|
|
5379
|
+
function turnedOnSentence(done) {
|
|
5380
|
+
if (done.length === 0) return "Nothing here was off.";
|
|
5381
|
+
const list = done.length === 1 ? done[0] : `${done.slice(0, -1).join(", ")} and ${done[done.length - 1]}`;
|
|
5382
|
+
return `Turned on ${list}.`;
|
|
5383
|
+
}
|
|
5384
|
+
|
|
5348
5385
|
// src/ItemPane.tsx
|
|
5349
5386
|
import { HistoryIcon, SettingsIcon, UsersIcon as UsersIcon2 } from "@ai-matrx/design-system/icons";
|
|
5350
5387
|
import { dropKeptDraft, keepDraft, readKeptDraft } from "@ai-matrx/kit/drafts";
|
|
@@ -5958,7 +5995,8 @@ function ItemPane(props) {
|
|
|
5958
5995
|
const [showBrowser, setShowBrowser] = useState27(false);
|
|
5959
5996
|
const [error, setError] = useState27(null);
|
|
5960
5997
|
const [destinations, setDestinations] = useState27({});
|
|
5961
|
-
const
|
|
5998
|
+
const [savedNew, setSavedNew] = useState27(false);
|
|
5999
|
+
const dirty = editing && !savedNew && isDirty(base, draft);
|
|
5962
6000
|
const declared = definition?.fields ?? [];
|
|
5963
6001
|
const prev = useRef14(null);
|
|
5964
6002
|
const paneRef = useRef14(null);
|
|
@@ -5981,8 +6019,11 @@ function ItemPane(props) {
|
|
|
5981
6019
|
setShowTags(false);
|
|
5982
6020
|
setShowDescription(false);
|
|
5983
6021
|
setShowRecovery(false);
|
|
6022
|
+
setSavedNew(false);
|
|
5984
6023
|
}, [item?.id, mode]);
|
|
5985
|
-
|
|
6024
|
+
const onDirtyRef = useRef14(onDirty);
|
|
6025
|
+
onDirtyRef.current = onDirty;
|
|
6026
|
+
useEffect16(() => onDirtyRef.current(dirty), [dirty]);
|
|
5986
6027
|
const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
|
|
5987
6028
|
useEffect16(() => {
|
|
5988
6029
|
if (editing && dirty) keepDraft(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
|
|
@@ -6039,6 +6080,8 @@ function ItemPane(props) {
|
|
|
6039
6080
|
const [withCode, n0, enrolled] = await withOtp(r.item, r.notice);
|
|
6040
6081
|
const [next, n] = await storeQueuedFiles(withCode, n0);
|
|
6041
6082
|
dropKeptDraft(keepKey);
|
|
6083
|
+
setSavedNew(true);
|
|
6084
|
+
onDirty(false);
|
|
6042
6085
|
onSaved(next, true, n, enrolled);
|
|
6043
6086
|
}
|
|
6044
6087
|
} catch (e) {
|
|
@@ -6101,12 +6144,7 @@ function ItemPane(props) {
|
|
|
6101
6144
|
if (!item) return;
|
|
6102
6145
|
setError(null);
|
|
6103
6146
|
try {
|
|
6104
|
-
|
|
6105
|
-
for (const f of fields) await confirmed(() => port.fields.updateField(item, f.id, { active: true }));
|
|
6106
|
-
if (fields.some((f) => f.key === OTP_SEED_KEY)) {
|
|
6107
|
-
const codes = await port.authenticator.get(item);
|
|
6108
|
-
if (codes && !codes.enabled) await confirmed(() => port.authenticator.setEnabled(item, true));
|
|
6109
|
-
}
|
|
6147
|
+
await turnBackOn(port, item, fields, { run: confirmed });
|
|
6110
6148
|
onChanged();
|
|
6111
6149
|
} catch (e) {
|
|
6112
6150
|
if (!wasCancelled(e)) setError(e instanceof Error ? e.message : "It could not be turned on.");
|
|
@@ -6161,7 +6199,7 @@ function ItemPane(props) {
|
|
|
6161
6199
|
"Unsaved"
|
|
6162
6200
|
] }) : null,
|
|
6163
6201
|
/* @__PURE__ */ jsx27(Button22, { variant: "quiet", disabled: busy, onClick: () => mode === "new" ? onCancelNew() : onMode("view"), children: dirty ? "Discard" : "Cancel" }),
|
|
6164
|
-
/* @__PURE__ */ jsx27(Button22, { variant: "primary", disabled: busy || sent !== null || draft.name.trim() === "" || mode === "edit" && !dirty || mode === "new" && owner === "person" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(recipient.trim()), onClick: () => void save(), children: mode === "new" && owner === "person" ? "Send" : "Save" })
|
|
6202
|
+
/* @__PURE__ */ jsx27(Button22, { variant: "primary", disabled: busy || savedNew || sent !== null || draft.name.trim() === "" || mode === "edit" && !dirty || mode === "new" && owner === "person" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(recipient.trim()), onClick: () => void save(), children: mode === "new" && owner === "person" ? "Send" : "Save" })
|
|
6165
6203
|
] }) : item ? /* @__PURE__ */ jsxs25("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
6166
6204
|
host.page && canUseOnSite(item, host.page.url) ? /* @__PURE__ */ jsx27(UseOnSiteButton, { port, item, pageUrl: host.page.url, onChanged: (next) => onChanged(next) }) : null,
|
|
6167
6205
|
host.fill && item.capabilities.canUse ? /* @__PURE__ */ jsx27(
|
|
@@ -6329,7 +6367,8 @@ function ItemPane(props) {
|
|
|
6329
6367
|
else delete next[i];
|
|
6330
6368
|
return next;
|
|
6331
6369
|
});
|
|
6332
|
-
|
|
6370
|
+
const stored = r?.url || normalizeLoginUrl(u);
|
|
6371
|
+
if (stored && stored !== u) setDraft((d) => ({ ...d, loginUrls: d.loginUrls.map((x, j) => j === i && x === u ? stored : x) }));
|
|
6333
6372
|
}),
|
|
6334
6373
|
onRemove: () => patch({ loginUrls: draft.loginUrls.filter((_, j) => j !== i) }),
|
|
6335
6374
|
removeLabel: "Remove website"
|
|
@@ -6741,8 +6780,16 @@ import { useEffect as useEffect18, useState as useState29 } from "react";
|
|
|
6741
6780
|
import { Button as Button24 } from "@ai-matrx/design-system/controls";
|
|
6742
6781
|
import { Fragment as Fragment19, jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
6743
6782
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
6744
|
-
function RestorePanel({
|
|
6783
|
+
function RestorePanel({
|
|
6784
|
+
lists,
|
|
6785
|
+
item,
|
|
6786
|
+
restore,
|
|
6787
|
+
turnOn,
|
|
6788
|
+
onClose
|
|
6789
|
+
}) {
|
|
6745
6790
|
const [preview, setPreview] = useState29(null);
|
|
6791
|
+
const [restored, setRestored] = useState29(null);
|
|
6792
|
+
const [turnedOn, setTurnedOn] = useState29(null);
|
|
6746
6793
|
const [error, setError] = useState29(null);
|
|
6747
6794
|
const [busy, setBusy] = useState29(false);
|
|
6748
6795
|
const [loading, setLoading] = useState29(Boolean(lists.preview));
|
|
@@ -6771,13 +6818,54 @@ function RestorePanel({ lists, item, restore, onClose }) {
|
|
|
6771
6818
|
setError(null);
|
|
6772
6819
|
try {
|
|
6773
6820
|
const result = await restore(preview?.supported ? preview.deletionId : void 0);
|
|
6774
|
-
if (result)
|
|
6821
|
+
if (!result) return;
|
|
6822
|
+
if (turnOn && !result.alreadyRestored && preview?.supported && !preview.priorWasDisabled) setRestored(result);
|
|
6823
|
+
else onClose();
|
|
6775
6824
|
} catch (e) {
|
|
6776
6825
|
setError(e instanceof Error && e.message ? e.message : "Restore did not complete. Try again.");
|
|
6777
6826
|
} finally {
|
|
6778
6827
|
setBusy(false);
|
|
6779
6828
|
}
|
|
6780
6829
|
};
|
|
6830
|
+
const runTurnOn = async () => {
|
|
6831
|
+
if (!restored || !turnOn) return;
|
|
6832
|
+
setBusy(true);
|
|
6833
|
+
setError(null);
|
|
6834
|
+
try {
|
|
6835
|
+
const said = await turnOn(restored.item);
|
|
6836
|
+
if (said !== null) setTurnedOn(said);
|
|
6837
|
+
} catch (e) {
|
|
6838
|
+
setError(e instanceof Error && e.message ? e.message : "It could not be turned on. Turn it on from the item.");
|
|
6839
|
+
} finally {
|
|
6840
|
+
setBusy(false);
|
|
6841
|
+
}
|
|
6842
|
+
};
|
|
6843
|
+
if (restored) {
|
|
6844
|
+
return /* @__PURE__ */ jsxs27(
|
|
6845
|
+
Panel,
|
|
6846
|
+
{
|
|
6847
|
+
title: `Restored "${item.name}"`,
|
|
6848
|
+
size: "md",
|
|
6849
|
+
onClose,
|
|
6850
|
+
footer: turnedOn ? /* @__PURE__ */ jsx29(Button24, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ jsxs27(Fragment19, { children: [
|
|
6851
|
+
/* @__PURE__ */ jsx29(Button24, { variant: "quiet", onClick: onClose, children: "Leave off" }),
|
|
6852
|
+
/* @__PURE__ */ jsx29(Button24, { variant: "primary", icon: /* @__PURE__ */ jsx29(RestoreGlyph, {}), disabled: busy, onClick: () => void runTurnOn(), children: busy ? "Turning on\u2026" : "Turn these back on" })
|
|
6853
|
+
] }),
|
|
6854
|
+
children: [
|
|
6855
|
+
/* @__PURE__ */ jsxs27(VaultSection, { title: turnedOn ? "Turned on" : "Back, turned off", children: [
|
|
6856
|
+
/* @__PURE__ */ jsx29(VaultRow, { label: "Came back", children: /* @__PURE__ */ jsxs27("span", { className: "text-foreground", children: [
|
|
6857
|
+
count(restored.restoredFields, "field"),
|
|
6858
|
+
", ",
|
|
6859
|
+
count(restored.restoredAttachments, "file")
|
|
6860
|
+
] }) }),
|
|
6861
|
+
turnedOn ? /* @__PURE__ */ jsx29(VaultRow, { label: "Now on", children: /* @__PURE__ */ jsx29("span", { role: "status", className: "text-foreground", children: turnedOn }) }) : /* @__PURE__ */ jsx29(VaultRow, { label: "Turns on", hint: "One press, nothing else changes", children: /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground", children: "The item, its fields, codes and browser fill" }) }),
|
|
6862
|
+
/* @__PURE__ */ jsx29(VaultRow, { label: "Stays off", hint: "Choose these again yourself", children: /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground", children: "Sharing, sandbox use" }) })
|
|
6863
|
+
] }),
|
|
6864
|
+
error ? /* @__PURE__ */ jsx29("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null
|
|
6865
|
+
]
|
|
6866
|
+
}
|
|
6867
|
+
);
|
|
6868
|
+
}
|
|
6781
6869
|
return /* @__PURE__ */ jsxs27(
|
|
6782
6870
|
Panel,
|
|
6783
6871
|
{
|
|
@@ -6818,7 +6906,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6818
6906
|
setMessage(null);
|
|
6819
6907
|
try {
|
|
6820
6908
|
const r = await confirmed(() => port.lists.restore(item, deletionId));
|
|
6821
|
-
setMessage({ tone: "ok", text: r.alreadyRestored ? `"${item.name}" was already restored.` : `Restored "${item.name}" with ${r.restoredFields} fields and ${r.restoredAttachments} files
|
|
6909
|
+
setMessage({ tone: "ok", text: r.alreadyRestored ? `"${item.name}" was already restored.` : `Restored "${item.name}" with ${r.restoredFields} fields and ${r.restoredAttachments} files, turned off.` });
|
|
6822
6910
|
onChanged();
|
|
6823
6911
|
return r;
|
|
6824
6912
|
} catch (e) {
|
|
@@ -6828,6 +6916,19 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6828
6916
|
setBusyId(null);
|
|
6829
6917
|
}
|
|
6830
6918
|
};
|
|
6919
|
+
const turnOn = async (item) => {
|
|
6920
|
+
try {
|
|
6921
|
+
const done = await turnBackOn(port, item, item.fields, { browserFill: true, run: confirmed });
|
|
6922
|
+
const said = turnedOnSentence(done);
|
|
6923
|
+
setMessage({ tone: "ok", text: `"${item.name}": ${said}` });
|
|
6924
|
+
onChanged();
|
|
6925
|
+
return said;
|
|
6926
|
+
} catch (e) {
|
|
6927
|
+
onChanged();
|
|
6928
|
+
if (wasCancelled(e)) return null;
|
|
6929
|
+
throw e;
|
|
6930
|
+
}
|
|
6931
|
+
};
|
|
6831
6932
|
return /* @__PURE__ */ jsxs28("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-3", children: [
|
|
6832
6933
|
header,
|
|
6833
6934
|
/* @__PURE__ */ jsx30(VaultSection, { title: "Trash", children: shown.length === 0 ? /* @__PURE__ */ jsx30(Empty, { children: deleted.length === 0 ? "The trash is empty." : "Nothing matches." }) : shown.map((item) => (
|
|
@@ -6841,7 +6942,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6841
6942
|
/* @__PURE__ */ jsx30(Button25, { variant: "outline", icon: /* @__PURE__ */ jsx30(RestoreGlyph, {}), disabled: busyId !== null || !item.deletion, onClick: () => setRestoring(item), children: "Restore" })
|
|
6842
6943
|
] }, item.id)
|
|
6843
6944
|
)) }),
|
|
6844
|
-
restoring ? /* @__PURE__ */ jsx30(RestorePanel, { lists: port.lists, item: restoring, restore: (deletionId) => restore(restoring, deletionId), onClose: () => setRestoring(null) }) : null,
|
|
6945
|
+
restoring ? /* @__PURE__ */ jsx30(RestorePanel, { lists: port.lists, item: restoring, restore: (deletionId) => restore(restoring, deletionId), turnOn, onClose: () => setRestoring(null) }) : null,
|
|
6845
6946
|
message2 ? /* @__PURE__ */ jsx30("p", { role: "status", className: message2.tone === "error" ? "px-1 text-sm text-destructive" : "px-1 text-sm text-muted-foreground", children: message2.text }) : null
|
|
6846
6947
|
] });
|
|
6847
6948
|
}
|
|
@@ -9106,7 +9207,7 @@ function createFieldsPort(ctx) {
|
|
|
9106
9207
|
const body = { initiation: "user" };
|
|
9107
9208
|
if (patch.uriMatchMode !== void 0) body.uri_match_mode = patch.uriMatchMode;
|
|
9108
9209
|
if (patch.browserFillEnabled !== void 0) body.browser_fill_enabled = patch.browserFillEnabled;
|
|
9109
|
-
if (patch.loginUrls !== void 0) body.login_urls = patch.loginUrls;
|
|
9210
|
+
if (patch.loginUrls !== void 0) body.login_urls = normalizeLoginUrls(patch.loginUrls);
|
|
9110
9211
|
if (patch.active !== void 0) body.status = patch.active ? "active" : "disabled";
|
|
9111
9212
|
await account3.updateItem(api, { path: { item_id: item.id }, body }, ctx.optsFor(item));
|
|
9112
9213
|
return reread(item);
|
|
@@ -9118,6 +9219,33 @@ function createFieldsPort(ctx) {
|
|
|
9118
9219
|
};
|
|
9119
9220
|
}
|
|
9120
9221
|
|
|
9222
|
+
// src/server-reasons.ts
|
|
9223
|
+
var GENERIC = [/please check your input/i, /^\s*request failed\s*\(\d+\)\s*$/i, /^\s*bad request\.?\s*$/i, /^\s*HTTP \d+\s*$/i];
|
|
9224
|
+
var isGeneric = (s) => GENERIC.some((re) => re.test(s));
|
|
9225
|
+
function cleanReason(detail) {
|
|
9226
|
+
const s = detail.replace(/^\s*validation error:\s*/i, "").replace(/^\s*value error,\s*/i, "").trim();
|
|
9227
|
+
return s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
|
|
9228
|
+
}
|
|
9229
|
+
function serverReason(e) {
|
|
9230
|
+
if (!e || typeof e !== "object") return null;
|
|
9231
|
+
const { status, detail, message: message2 } = e;
|
|
9232
|
+
if (typeof status !== "number" || status < 400 || status >= 500) return null;
|
|
9233
|
+
if (typeof detail !== "string" || !detail.trim() || isGeneric(detail)) return null;
|
|
9234
|
+
const shown = typeof message2 === "string" ? message2 : "";
|
|
9235
|
+
if (shown && !isGeneric(shown)) return null;
|
|
9236
|
+
return cleanReason(detail);
|
|
9237
|
+
}
|
|
9238
|
+
function withReason(e) {
|
|
9239
|
+
const reason = serverReason(e);
|
|
9240
|
+
if (reason) Object.assign(e, { message: reason, userMessage: reason });
|
|
9241
|
+
return e;
|
|
9242
|
+
}
|
|
9243
|
+
function withServerReasons(api) {
|
|
9244
|
+
const wrapped = Object.create(api);
|
|
9245
|
+
wrapped.call = (...args) => api.call(...args).catch((e) => Promise.reject(withReason(e)));
|
|
9246
|
+
return wrapped;
|
|
9247
|
+
}
|
|
9248
|
+
|
|
9121
9249
|
// src/io/api.ts
|
|
9122
9250
|
import * as account4 from "@ai-matrx/api/account";
|
|
9123
9251
|
var orgOpts = (organizationId) => organizationId ? { organizationId } : void 0;
|
|
@@ -9390,7 +9518,7 @@ function createSharingPort(ctx, options = {}) {
|
|
|
9390
9518
|
definition_key: definition.key,
|
|
9391
9519
|
provider_key: definition.providerKey,
|
|
9392
9520
|
tags: draft.tags,
|
|
9393
|
-
login_urls: draft.loginUrls,
|
|
9521
|
+
login_urls: normalizeLoginUrls(draft.loginUrls),
|
|
9394
9522
|
notes: draft.notes || null,
|
|
9395
9523
|
generate_field_key: generateFieldKey,
|
|
9396
9524
|
initiation: "user",
|
|
@@ -9587,7 +9715,8 @@ async function retrying(run, tries = 3) {
|
|
|
9587
9715
|
}
|
|
9588
9716
|
}
|
|
9589
9717
|
}
|
|
9590
|
-
function createApiVaultPort(
|
|
9718
|
+
function createApiVaultPort(hostApi, options = {}) {
|
|
9719
|
+
const api = withServerReasons(hostApi);
|
|
9591
9720
|
let defs = /* @__PURE__ */ new Map();
|
|
9592
9721
|
let auth = /* @__PURE__ */ new Map();
|
|
9593
9722
|
let orgs = [];
|
|
@@ -9742,6 +9871,7 @@ function createApiVaultPort(api, options = {}) {
|
|
|
9742
9871
|
const declared = definition.fields;
|
|
9743
9872
|
const encrypted = declared.filter((f) => f.storage === "encrypted" && (draft.values[f.key] ?? "") !== "");
|
|
9744
9873
|
const meta = declared.filter((f) => f.storage === "metadata" && (draft.values[f.key] ?? "") !== "");
|
|
9874
|
+
const loginUrls = normalizeLoginUrls(draft.loginUrls);
|
|
9745
9875
|
const w = await account9.createItem(api, {
|
|
9746
9876
|
body: {
|
|
9747
9877
|
display_name: draft.name.trim(),
|
|
@@ -9749,10 +9879,10 @@ function createApiVaultPort(api, options = {}) {
|
|
|
9749
9879
|
definition_key: definition.key,
|
|
9750
9880
|
provider_key: definition.providerKey,
|
|
9751
9881
|
tags: draft.tags,
|
|
9752
|
-
login_urls:
|
|
9882
|
+
login_urls: loginUrls,
|
|
9753
9883
|
// A login a person saves with its website is offered on that website (the server's own
|
|
9754
9884
|
// default is off, which made "Save a login" on a page answer "No saved login" there).
|
|
9755
|
-
...draft.browser ? { uri_match_mode: draft.browser.uriMatchMode, browser_fill_enabled: draft.browser.browserFillEnabled } :
|
|
9885
|
+
...draft.browser ? { uri_match_mode: draft.browser.uriMatchMode, browser_fill_enabled: draft.browser.browserFillEnabled } : loginUrls.length > 0 ? { browser_fill_enabled: true } : {},
|
|
9756
9886
|
notes: draft.notes || null,
|
|
9757
9887
|
principal: organizationId ? { type: "organization", organization_id: organizationId } : { type: "user" },
|
|
9758
9888
|
initiation: "user",
|
|
@@ -9779,7 +9909,7 @@ function createApiVaultPort(api, options = {}) {
|
|
|
9779
9909
|
else body.description = draft.description.trim();
|
|
9780
9910
|
}
|
|
9781
9911
|
if (JSON.stringify(draft.tags) !== JSON.stringify(item.tags)) body.tags = draft.tags;
|
|
9782
|
-
if (JSON.stringify(draft.loginUrls) !== JSON.stringify(item.loginUrls)) body.login_urls = draft.loginUrls;
|
|
9912
|
+
if (JSON.stringify(draft.loginUrls) !== JSON.stringify(item.loginUrls)) body.login_urls = normalizeLoginUrls(draft.loginUrls);
|
|
9783
9913
|
if (draft.notes !== item.notes) {
|
|
9784
9914
|
if (draft.notes === "") body.clear_notes = true;
|
|
9785
9915
|
else body.notes = draft.notes;
|