@trops/dash-core 0.1.614 → 0.1.616
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/electron/index.js +144 -63
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +257 -210
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +256 -209
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -9758,6 +9758,17 @@ async function pollForToken$1(deviceCode) {
|
|
|
9758
9758
|
s.set("tokenType", data.token_type);
|
|
9759
9759
|
s.set("authenticatedAt", new Date().toISOString());
|
|
9760
9760
|
|
|
9761
|
+
// Persist the Cognito refresh token (+ the client id / region needed to
|
|
9762
|
+
// use it) when the registry forwarded it. This is what lets the app mint
|
|
9763
|
+
// fresh access tokens directly against Cognito on expiry instead of
|
|
9764
|
+
// silently 401-ing every registry call after ~1h. Older registries (or a
|
|
9765
|
+
// browser whose Amplify storage didn't surface the refresh token) omit
|
|
9766
|
+
// these — the app then falls back to re-authenticating on expiry.
|
|
9767
|
+
if (data.refresh_token) s.set("refreshToken", data.refresh_token);
|
|
9768
|
+
if (data.cognito_client_id)
|
|
9769
|
+
s.set("cognitoClientId", data.cognito_client_id);
|
|
9770
|
+
if (data.cognito_region) s.set("cognitoRegion", data.cognito_region);
|
|
9771
|
+
|
|
9761
9772
|
return {
|
|
9762
9773
|
status: "authorized",
|
|
9763
9774
|
token: data.access_token,
|
|
@@ -9768,6 +9779,106 @@ async function pollForToken$1(deviceCode) {
|
|
|
9768
9779
|
throw new Error(`Unexpected response: ${response.status}`);
|
|
9769
9780
|
}
|
|
9770
9781
|
|
|
9782
|
+
/**
|
|
9783
|
+
* Decode a JWT's `exp` claim (no signature verification — we only use it to
|
|
9784
|
+
* decide whether to pre-emptively refresh) and report whether it's expired,
|
|
9785
|
+
* with a 30s skew so we refresh slightly early rather than racing expiry.
|
|
9786
|
+
* Returns false on any parse failure so a malformed token falls through to
|
|
9787
|
+
* the normal request (and the reactive 401 path) rather than forcing churn.
|
|
9788
|
+
*/
|
|
9789
|
+
function isAccessTokenExpired(token) {
|
|
9790
|
+
try {
|
|
9791
|
+
const seg = token.split(".")[1];
|
|
9792
|
+
const payload = JSON.parse(Buffer.from(seg, "base64").toString("utf8"));
|
|
9793
|
+
if (!payload.exp) return false;
|
|
9794
|
+
return Date.now() >= payload.exp * 1000 - 30000;
|
|
9795
|
+
} catch {
|
|
9796
|
+
return false;
|
|
9797
|
+
}
|
|
9798
|
+
}
|
|
9799
|
+
|
|
9800
|
+
/**
|
|
9801
|
+
* Mint a fresh access token from the stored Cognito refresh token via
|
|
9802
|
+
* Cognito's `InitiateAuth` (REFRESH_TOKEN_AUTH). The user-pool client is
|
|
9803
|
+
* public (no secret), so no SECRET_HASH is required. Returns true and updates
|
|
9804
|
+
* the stored access token on success; false if there's no refresh token or
|
|
9805
|
+
* Cognito rejects it (expired/revoked — caller decides whether to sign out).
|
|
9806
|
+
*/
|
|
9807
|
+
async function refreshAccessToken() {
|
|
9808
|
+
const s = getStore$3();
|
|
9809
|
+
const refreshToken = s.get("refreshToken");
|
|
9810
|
+
const clientId = s.get("cognitoClientId");
|
|
9811
|
+
const region = s.get("cognitoRegion") || "us-east-1";
|
|
9812
|
+
if (!refreshToken || !clientId) return false;
|
|
9813
|
+
|
|
9814
|
+
try {
|
|
9815
|
+
const response = await fetch(
|
|
9816
|
+
`https://cognito-idp.${region}.amazonaws.com/`,
|
|
9817
|
+
{
|
|
9818
|
+
method: "POST",
|
|
9819
|
+
headers: {
|
|
9820
|
+
"Content-Type": "application/x-amz-json-1.1",
|
|
9821
|
+
"X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth",
|
|
9822
|
+
},
|
|
9823
|
+
body: JSON.stringify({
|
|
9824
|
+
AuthFlow: "REFRESH_TOKEN_AUTH",
|
|
9825
|
+
ClientId: clientId,
|
|
9826
|
+
AuthParameters: { REFRESH_TOKEN: refreshToken },
|
|
9827
|
+
}),
|
|
9828
|
+
},
|
|
9829
|
+
);
|
|
9830
|
+
if (!response.ok) return false;
|
|
9831
|
+
|
|
9832
|
+
const data = await response.json();
|
|
9833
|
+
const result = data.AuthenticationResult;
|
|
9834
|
+
if (!result || !result.AccessToken) return false;
|
|
9835
|
+
|
|
9836
|
+
s.set("accessToken", result.AccessToken);
|
|
9837
|
+
s.set("authenticatedAt", new Date().toISOString());
|
|
9838
|
+
// REFRESH_TOKEN_AUTH normally does NOT return a new refresh token, but
|
|
9839
|
+
// honor one if rotation is ever enabled.
|
|
9840
|
+
if (result.RefreshToken) s.set("refreshToken", result.RefreshToken);
|
|
9841
|
+
return true;
|
|
9842
|
+
} catch {
|
|
9843
|
+
return false;
|
|
9844
|
+
}
|
|
9845
|
+
}
|
|
9846
|
+
|
|
9847
|
+
/**
|
|
9848
|
+
* Authenticated fetch with transparent token refresh.
|
|
9849
|
+
*
|
|
9850
|
+
* - Injects the stored access token as a Bearer header (when present).
|
|
9851
|
+
* - Pre-emptively refreshes when the access token is already expired.
|
|
9852
|
+
* - On a 401, attempts one refresh + retry before giving up.
|
|
9853
|
+
*
|
|
9854
|
+
* Returns a real `Response`. Callers that need to react to a still-401
|
|
9855
|
+
* (refresh failed → truly signed out) check `response.status` and decide
|
|
9856
|
+
* whether to clear credentials. Anonymous callers (no token) just get an
|
|
9857
|
+
* unauthenticated request.
|
|
9858
|
+
*/
|
|
9859
|
+
async function authedFetch$1(url, options = {}) {
|
|
9860
|
+
let stored = getStoredToken$5();
|
|
9861
|
+
|
|
9862
|
+
if (stored && isAccessTokenExpired(stored.token)) {
|
|
9863
|
+
if (await refreshAccessToken()) stored = getStoredToken$5();
|
|
9864
|
+
}
|
|
9865
|
+
|
|
9866
|
+
const withAuth = (tok) => {
|
|
9867
|
+
const headers = { ...(options.headers || {}) };
|
|
9868
|
+
if (tok) headers.Authorization = `Bearer ${tok}`;
|
|
9869
|
+
return fetch(url, { ...options, headers });
|
|
9870
|
+
};
|
|
9871
|
+
|
|
9872
|
+
let response = await withAuth(stored && stored.token);
|
|
9873
|
+
if (response.status === 401 && stored) {
|
|
9874
|
+
if (await refreshAccessToken()) {
|
|
9875
|
+
const fresh = getStoredToken$5();
|
|
9876
|
+
response = await withAuth(fresh && fresh.token);
|
|
9877
|
+
}
|
|
9878
|
+
}
|
|
9879
|
+
return response;
|
|
9880
|
+
}
|
|
9881
|
+
|
|
9771
9882
|
/**
|
|
9772
9883
|
* Get the stored auth token.
|
|
9773
9884
|
*
|
|
@@ -9817,14 +9928,11 @@ async function getRegistryProfile$3() {
|
|
|
9817
9928
|
if (!stored) return null;
|
|
9818
9929
|
|
|
9819
9930
|
try {
|
|
9820
|
-
const response = await
|
|
9821
|
-
headers: {
|
|
9822
|
-
Authorization: `Bearer ${stored.token}`,
|
|
9823
|
-
},
|
|
9824
|
-
});
|
|
9931
|
+
const response = await authedFetch$1(`${REGISTRY_BASE_URL$2}/api/auth/me`);
|
|
9825
9932
|
|
|
9826
9933
|
if (response.status === 401) {
|
|
9827
|
-
//
|
|
9934
|
+
// Still 401 after authedFetch tried to refresh — the refresh token is
|
|
9935
|
+
// gone/expired too, so the session is genuinely over. Clear it.
|
|
9828
9936
|
clearToken$2();
|
|
9829
9937
|
return null;
|
|
9830
9938
|
}
|
|
@@ -9861,10 +9969,9 @@ async function updateRegistryProfile$1(updates) {
|
|
|
9861
9969
|
if (!stored) return null;
|
|
9862
9970
|
|
|
9863
9971
|
try {
|
|
9864
|
-
const response = await
|
|
9972
|
+
const response = await authedFetch$1(`${REGISTRY_BASE_URL$2}/api/auth/me`, {
|
|
9865
9973
|
method: "PATCH",
|
|
9866
9974
|
headers: {
|
|
9867
|
-
Authorization: `Bearer ${stored.token}`,
|
|
9868
9975
|
"Content-Type": "application/json",
|
|
9869
9976
|
},
|
|
9870
9977
|
body: JSON.stringify(updates),
|
|
@@ -9893,11 +10000,9 @@ async function getRegistryPackages$1() {
|
|
|
9893
10000
|
if (!stored) return null;
|
|
9894
10001
|
|
|
9895
10002
|
try {
|
|
9896
|
-
const response = await
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
},
|
|
9900
|
-
});
|
|
10003
|
+
const response = await authedFetch$1(
|
|
10004
|
+
`${REGISTRY_BASE_URL$2}/api/auth/me/packages`,
|
|
10005
|
+
);
|
|
9901
10006
|
|
|
9902
10007
|
if (response.status === 401) {
|
|
9903
10008
|
clearToken$2();
|
|
@@ -9924,12 +10029,11 @@ async function updateRegistryPackage$1(scope, name, updates) {
|
|
|
9924
10029
|
if (!stored) return null;
|
|
9925
10030
|
|
|
9926
10031
|
try {
|
|
9927
|
-
const response = await
|
|
10032
|
+
const response = await authedFetch$1(
|
|
9928
10033
|
`${REGISTRY_BASE_URL$2}/api/packages/${encodeURIComponent(scope)}/${encodeURIComponent(name)}`,
|
|
9929
10034
|
{
|
|
9930
10035
|
method: "PATCH",
|
|
9931
10036
|
headers: {
|
|
9932
|
-
Authorization: `Bearer ${stored.token}`,
|
|
9933
10037
|
"Content-Type": "application/json",
|
|
9934
10038
|
},
|
|
9935
10039
|
body: JSON.stringify(updates),
|
|
@@ -9966,13 +10070,10 @@ async function deleteRegistryPackage$1(scope, name) {
|
|
|
9966
10070
|
}
|
|
9967
10071
|
|
|
9968
10072
|
try {
|
|
9969
|
-
const response = await
|
|
10073
|
+
const response = await authedFetch$1(
|
|
9970
10074
|
`${REGISTRY_BASE_URL$2}/api/packages/${encodeURIComponent(scope)}/${encodeURIComponent(name)}`,
|
|
9971
10075
|
{
|
|
9972
10076
|
method: "DELETE",
|
|
9973
|
-
headers: {
|
|
9974
|
-
Authorization: `Bearer ${stored.token}`,
|
|
9975
|
-
},
|
|
9976
10077
|
},
|
|
9977
10078
|
);
|
|
9978
10079
|
|
|
@@ -10035,6 +10136,9 @@ var registryAuthController$2 = {
|
|
|
10035
10136
|
updateRegistryPackage: updateRegistryPackage$1,
|
|
10036
10137
|
deleteRegistryPackage: deleteRegistryPackage$1,
|
|
10037
10138
|
clearToken: clearToken$2,
|
|
10139
|
+
refreshAccessToken,
|
|
10140
|
+
authedFetch: authedFetch$1,
|
|
10141
|
+
isAccessTokenExpired,
|
|
10038
10142
|
};
|
|
10039
10143
|
|
|
10040
10144
|
/**
|
|
@@ -38834,18 +38938,7 @@ const path$9 = require$$1$2;
|
|
|
38834
38938
|
const fs$7 = require$$0$3;
|
|
38835
38939
|
const os$1 = require$$2;
|
|
38836
38940
|
const { toPackageId } = packageId;
|
|
38837
|
-
const { getStoredToken: getStoredToken$4 } = registryAuthController$2;
|
|
38838
|
-
|
|
38839
|
-
/**
|
|
38840
|
-
* Build request headers for the registry. When the user is signed in, we
|
|
38841
|
-
* include the Bearer token so the server returns private packages that
|
|
38842
|
-
* the user owns or has been granted entitlements for. Anonymous fetches
|
|
38843
|
-
* still work and simply return only public packages.
|
|
38844
|
-
*/
|
|
38845
|
-
function buildAuthHeaders() {
|
|
38846
|
-
const stored = getStoredToken$4();
|
|
38847
|
-
return stored?.token ? { Authorization: `Bearer ${stored.token}` } : {};
|
|
38848
|
-
}
|
|
38941
|
+
const { getStoredToken: getStoredToken$4, authedFetch } = registryAuthController$2;
|
|
38849
38942
|
|
|
38850
38943
|
// Default registry API base URL
|
|
38851
38944
|
const DEFAULT_REGISTRY_API_URL = "https://main.d919rwhuzp7rj.amplifyapp.com";
|
|
@@ -38923,9 +39016,7 @@ async function fetchRegistryIndex(forceRefresh = false) {
|
|
|
38923
39016
|
"[RegistryController] Fetching registry from:",
|
|
38924
39017
|
registryUrl,
|
|
38925
39018
|
);
|
|
38926
|
-
const response = await
|
|
38927
|
-
headers: buildAuthHeaders(),
|
|
38928
|
-
});
|
|
39019
|
+
const response = await authedFetch(registryUrl);
|
|
38929
39020
|
if (!response.ok) {
|
|
38930
39021
|
throw new Error(
|
|
38931
39022
|
`Failed to fetch registry: ${response.status} ${response.statusText}`,
|
|
@@ -38940,9 +39031,7 @@ async function fetchRegistryIndex(forceRefresh = false) {
|
|
|
38940
39031
|
`${process.env.DASH_REGISTRY_API_URL || DEFAULT_REGISTRY_API_URL}/api/packages`;
|
|
38941
39032
|
console.log("[RegistryController] Fetching registry from:", registryUrl);
|
|
38942
39033
|
|
|
38943
|
-
const response = await
|
|
38944
|
-
headers: buildAuthHeaders(),
|
|
38945
|
-
});
|
|
39034
|
+
const response = await authedFetch(registryUrl);
|
|
38946
39035
|
if (!response.ok) {
|
|
38947
39036
|
throw new Error(
|
|
38948
39037
|
`Failed to fetch registry: ${response.status} ${response.statusText}`,
|
|
@@ -39265,13 +39354,13 @@ async function checkUpdates(installedWidgets = []) {
|
|
|
39265
39354
|
]) {
|
|
39266
39355
|
const url = `${registryBase}${endpointPath}`;
|
|
39267
39356
|
try {
|
|
39268
|
-
|
|
39357
|
+
// authedFetch injects the Bearer token and transparently refreshes it
|
|
39358
|
+
// on expiry. Auth is optional here but widens what /resolve returns
|
|
39359
|
+
// for private packages where ownership matters.
|
|
39360
|
+
const response = await authedFetch(url, {
|
|
39269
39361
|
method: "POST",
|
|
39270
39362
|
headers: {
|
|
39271
39363
|
"Content-Type": "application/json",
|
|
39272
|
-
// Auth is optional but widens what /resolve returns for
|
|
39273
|
-
// private packages where ownership matters.
|
|
39274
|
-
...buildAuthHeaders(),
|
|
39275
39364
|
},
|
|
39276
39365
|
body: refsBody,
|
|
39277
39366
|
});
|
|
@@ -39441,21 +39530,17 @@ async function fetchPackageSource(packageName, componentName = null) {
|
|
|
39441
39530
|
);
|
|
39442
39531
|
}
|
|
39443
39532
|
|
|
39444
|
-
const fetchOpts = {};
|
|
39445
39533
|
const registryBase =
|
|
39446
39534
|
process.env.DASH_REGISTRY_API_URL ||
|
|
39447
39535
|
"https://main.d919rwhuzp7rj.amplifyapp.com";
|
|
39448
|
-
|
|
39536
|
+
// Use authedFetch (Bearer + auto-refresh) only for registry-hosted URLs;
|
|
39537
|
+
// external download URLs (e.g. GitHub releases) must NOT receive our token.
|
|
39538
|
+
const isRegistryUrl =
|
|
39449
39539
|
pkg.downloadUrl.includes(registryBase) ||
|
|
39450
|
-
pkg.downloadUrl.includes("/api/packages/")
|
|
39451
|
-
|
|
39452
|
-
|
|
39453
|
-
|
|
39454
|
-
fetchOpts.headers = { Authorization: `Bearer ${auth.token}` };
|
|
39455
|
-
}
|
|
39456
|
-
}
|
|
39457
|
-
|
|
39458
|
-
const response = await fetch(pkg.downloadUrl, fetchOpts);
|
|
39540
|
+
pkg.downloadUrl.includes("/api/packages/");
|
|
39541
|
+
const response = isRegistryUrl
|
|
39542
|
+
? await authedFetch(pkg.downloadUrl)
|
|
39543
|
+
: await fetch(pkg.downloadUrl);
|
|
39459
39544
|
if (!response.ok) {
|
|
39460
39545
|
if (response.status === 401) {
|
|
39461
39546
|
throw new Error("Authentication required to preview this package");
|
|
@@ -39630,21 +39715,17 @@ async function fetchPackageManifest(packageName) {
|
|
|
39630
39715
|
);
|
|
39631
39716
|
}
|
|
39632
39717
|
|
|
39633
|
-
const fetchOpts = {};
|
|
39634
39718
|
const registryBase =
|
|
39635
39719
|
process.env.DASH_REGISTRY_API_URL ||
|
|
39636
39720
|
"https://main.d919rwhuzp7rj.amplifyapp.com";
|
|
39637
|
-
|
|
39721
|
+
// Use authedFetch (Bearer + auto-refresh) only for registry-hosted URLs;
|
|
39722
|
+
// external download URLs (e.g. GitHub releases) must NOT receive our token.
|
|
39723
|
+
const isRegistryUrl =
|
|
39638
39724
|
pkg.downloadUrl.includes(registryBase) ||
|
|
39639
|
-
pkg.downloadUrl.includes("/api/packages/")
|
|
39640
|
-
|
|
39641
|
-
|
|
39642
|
-
|
|
39643
|
-
fetchOpts.headers = { Authorization: `Bearer ${auth.token}` };
|
|
39644
|
-
}
|
|
39645
|
-
}
|
|
39646
|
-
|
|
39647
|
-
const response = await fetch(pkg.downloadUrl, fetchOpts);
|
|
39725
|
+
pkg.downloadUrl.includes("/api/packages/");
|
|
39726
|
+
const response = isRegistryUrl
|
|
39727
|
+
? await authedFetch(pkg.downloadUrl)
|
|
39728
|
+
: await fetch(pkg.downloadUrl);
|
|
39648
39729
|
if (!response.ok) {
|
|
39649
39730
|
if (response.status === 401) {
|
|
39650
39731
|
throw new Error("Authentication required to fetch this package manifest");
|