@ai-matrx/vault 0.1.37 → 0.1.39
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 +9 -2
- package/dist/index.cjs +39 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +39 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.39
|
|
4
|
+
|
|
5
|
+
- **Organization vaults never read as empty by mistake** (2026-10-23): a 404 from `GET /vault/organization-items` still falls back to one read per organization, but now says so once per port (new `ApiVaultPortOptions.onHostProblem(message, detail)`; without it, `console.warn`); an organization the server refused, names unavailable or leaves out is listed under `unavailable`, never shown as an empty vault; the camera note in Add authenticator is one line of 60 characters or fewer ("No camera. Paste the key or choose a QR image."). Proof: `src/organization-items-load.test.ts`, `src/first-code-closes.test.tsx`, `src/review-0-1-36.test.tsx`, `src/review-0-1-37.test.tsx`. Consumer action: needs `@ai-matrx/design-system` with the Select hint that never truncates (the release train publishes both); a host may pass `onHostProblem` to forward it to its error capture; nothing else.
|
|
6
|
+
|
|
7
|
+
## 0.1.38
|
|
8
|
+
|
|
9
|
+
- **Website vault walk fixes** (2026-10-23): a row with an authenticator copies its one-time code from the hover quick actions ("One-time code copied"); "Add authenticator" shows the setup-key box first and starts the camera by itself only when the device has one, with the preview and any camera failure UNDER the box as a small note (no window over it; `hasCameraDevice()` in `authenticator/qr.ts`, `QrScanInline` replaces `QrScanPanel`); the first-code window closes when the person moves to another view, item, edit or panel (`useShownUntilMove`); the Vault switcher, Move to and Copy to list organizations recently used and non-empty first, then by name (`orderOrganizations`), tell same-named ones apart by short id (`organizationHints`) and show a search from `vault.organization_search_at` (new knob, default 8, read through `host.knobs`; `host.organizationSearchAt` overrides); after "Copy made in …" the panel offers Open copy (`ItemPanelProps.onOpenItem`); the load reads every organization vault in ONE request (`GET /vault/organization-items`) instead of one per organization, own items still first. Proof: `src/review-0-1-37.test.tsx`. Consumer action: needs `@ai-matrx/api` with `account.organizationItems` and `@ai-matrx/design-system` with Select `hint`/`searchAt` (the release train publishes all three); nothing else.
|
|
10
|
+
|
|
3
11
|
## 0.1.37
|
|
4
12
|
|
|
5
|
-
|
|
6
|
-
Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/vault/src`.
|
|
13
|
+
- **Website vault walk fixes, items 7-11** (2026-10-23): a row with an authenticator copies its one-time code from the hover quick actions; "Add authenticator" shows the setup-key box first and starts the camera only when the device has one (`hasCameraDevice()`); the first-code window closes when the person moves to another view, item, edit or panel (`useShownUntilMove`); the Vault switcher, Move to and Copy to list recently used and non-empty organizations first, then by name, with short ids for same-named ones and a search from `vault.organization_search_at` (`orderOrganizations`, `organizationHints`, `ORGANIZATION_SEARCH_AT_KNOB`); after "Copy made in ..." the panel offers Open copy (`ItemPanelProps.onOpenItem`). Proof: `src/review-0-1-37.test.tsx`. Consumer action: none.
|
|
7
14
|
|
|
8
15
|
## 0.1.36
|
|
9
16
|
|
package/dist/index.cjs
CHANGED
|
@@ -1928,6 +1928,11 @@ function useCanScan() {
|
|
|
1928
1928
|
}, []);
|
|
1929
1929
|
return ok;
|
|
1930
1930
|
}
|
|
1931
|
+
var CAMERA_NOTES = {
|
|
1932
|
+
blocked: "Camera blocked. Paste the key or choose a QR image.",
|
|
1933
|
+
missing: "No camera. Paste the key or choose a QR image.",
|
|
1934
|
+
failed: "Camera did not start. Paste the key or choose a QR image."
|
|
1935
|
+
};
|
|
1931
1936
|
function QrScanInline({ onResult, onClose }) {
|
|
1932
1937
|
const video = (0, import_react10.useRef)(null);
|
|
1933
1938
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
@@ -1973,7 +1978,7 @@ function QrScanInline({ onResult, onClose }) {
|
|
|
1973
1978
|
}).catch((e) => {
|
|
1974
1979
|
if (!live) return;
|
|
1975
1980
|
const name = e?.name;
|
|
1976
|
-
setError(name === "NotAllowedError" ?
|
|
1981
|
+
setError(name === "NotAllowedError" ? CAMERA_NOTES.blocked : name === "NotFoundError" ? CAMERA_NOTES.missing : CAMERA_NOTES.failed);
|
|
1977
1982
|
});
|
|
1978
1983
|
return () => {
|
|
1979
1984
|
live = false;
|
|
@@ -1983,10 +1988,7 @@ function QrScanInline({ onResult, onClose }) {
|
|
|
1983
1988
|
if (error) {
|
|
1984
1989
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "flex items-center gap-2 px-1 pt-1 text-xs text-muted-foreground", role: "status", "data-camera-note": "", children: [
|
|
1985
1990
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CameraGlyph, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
1986
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
1987
|
-
error,
|
|
1988
|
-
" Paste the setup key or choose a QR image."
|
|
1989
|
-
] }),
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "min-w-0 flex-1 truncate", children: error }),
|
|
1990
1992
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_controls6.Button, { variant: "quiet", onClick: onClose, children: "Dismiss" })
|
|
1991
1993
|
] });
|
|
1992
1994
|
}
|
|
@@ -10025,6 +10027,13 @@ async function retrying(run, tries = 3) {
|
|
|
10025
10027
|
}
|
|
10026
10028
|
function createApiVaultPort(hostApi, options = {}) {
|
|
10027
10029
|
const api = withServerReasons(hostApi);
|
|
10030
|
+
let problemTold = false;
|
|
10031
|
+
const hostProblem = (message2, detail) => {
|
|
10032
|
+
if (problemTold) return;
|
|
10033
|
+
problemTold = true;
|
|
10034
|
+
if (options.onHostProblem) options.onHostProblem(message2, detail);
|
|
10035
|
+
else console.warn(`[vault] ${message2}`, detail);
|
|
10036
|
+
};
|
|
10028
10037
|
let defs = /* @__PURE__ */ new Map();
|
|
10029
10038
|
let auth = /* @__PURE__ */ new Map();
|
|
10030
10039
|
let orgs = [];
|
|
@@ -10072,6 +10081,8 @@ function createApiVaultPort(hostApi, options = {}) {
|
|
|
10072
10081
|
const sharedP = retrying(() => account9.sharedWithMe(api));
|
|
10073
10082
|
const quiet = (p) => void p.catch(() => void 0);
|
|
10074
10083
|
[catalogP, authP, userP, sharedP].forEach(quiet);
|
|
10084
|
+
const orgItemsP = retrying(() => account9.organizationItems(api));
|
|
10085
|
+
quiet(orgItemsP);
|
|
10075
10086
|
const raw = {
|
|
10076
10087
|
orgLists: [],
|
|
10077
10088
|
orgsKnown: options.organizations !== void 0,
|
|
@@ -10119,6 +10130,29 @@ function createApiVaultPort(hostApi, options = {}) {
|
|
|
10119
10130
|
raw.orgLists = orgs.map(() => void 0);
|
|
10120
10131
|
raw.orgsKnown = true;
|
|
10121
10132
|
progress();
|
|
10133
|
+
const one = await orgItemsP.then(
|
|
10134
|
+
(r) => r,
|
|
10135
|
+
(e) => {
|
|
10136
|
+
if (e?.status === 404) {
|
|
10137
|
+
hostProblem("GET /vault/organization-items answered 404; reading each organization vault separately", e);
|
|
10138
|
+
return null;
|
|
10139
|
+
}
|
|
10140
|
+
return "failed";
|
|
10141
|
+
}
|
|
10142
|
+
);
|
|
10143
|
+
if (one) {
|
|
10144
|
+
const byOrg = one === "failed" ? /* @__PURE__ */ new Map() : new Map(one.views.map((v) => [v.organization_id, v.items]));
|
|
10145
|
+
const failed = one === "failed" ? new Set(orgs.map((o) => o.id)) : new Set(one.unavailable);
|
|
10146
|
+
const settled = orgs.map((o, i) => {
|
|
10147
|
+
const items = byOrg.get(o.id);
|
|
10148
|
+
if (failed.has(o.id) || items === void 0) return Promise.reject(new Error(`${o.name} is unavailable`));
|
|
10149
|
+
raw.orgLists[i] = { items, count: items.length };
|
|
10150
|
+
return Promise.resolve(raw.orgLists[i]);
|
|
10151
|
+
});
|
|
10152
|
+
settled.forEach(quiet);
|
|
10153
|
+
progress();
|
|
10154
|
+
return settled;
|
|
10155
|
+
}
|
|
10122
10156
|
return orgs.map((o, i) => {
|
|
10123
10157
|
const p = retrying(() => account9.listItems(api, { query: { principal_type: "organization", organization_id: o.id } }, { organizationId: o.id }));
|
|
10124
10158
|
const arrived = p.then((l) => {
|