@calimero-network/mero-js 19.9.0 → 19.11.0
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/admin-api/admin-client.d.ts +9 -1
- package/dist/admin-api/admin-client.js +10 -0
- package/dist/admin-api/admin-types.d.ts +44 -0
- package/dist/cloud/cloud-client.d.ts +74 -0
- package/dist/cloud/cloud-client.js +95 -0
- package/dist/cloud/index.d.ts +1 -1
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +109 -0
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +109 -0
- package/dist/index.mjs.map +2 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1363,6 +1363,21 @@ var AdminApiClient = class {
|
|
|
1363
1363
|
)
|
|
1364
1364
|
);
|
|
1365
1365
|
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Replace a device's scope outright, in one root-signed op.
|
|
1368
|
+
*
|
|
1369
|
+
* {@link relinkAccountDevice} only ever adds applications; this is how a
|
|
1370
|
+
* scope is narrowed - or an `all` device is given a fixed list instead. The
|
|
1371
|
+
* device need not be online.
|
|
1372
|
+
*/
|
|
1373
|
+
async rescopeAccountDevice(deviceId, request) {
|
|
1374
|
+
return unwrap(
|
|
1375
|
+
await this.httpClient.put(
|
|
1376
|
+
`/admin-api/account/devices/${encodeURIComponent(deviceId)}/scope`,
|
|
1377
|
+
request
|
|
1378
|
+
)
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1366
1381
|
/**
|
|
1367
1382
|
* Every device of this account, as this node sees them - its own included.
|
|
1368
1383
|
*
|
|
@@ -5277,6 +5292,100 @@ var CloudClient = class {
|
|
|
5277
5292
|
alreadyLinked: body.already_linked === true
|
|
5278
5293
|
};
|
|
5279
5294
|
}
|
|
5295
|
+
/**
|
|
5296
|
+
* Where to send someone to authorise linking this account, and what to expect
|
|
5297
|
+
* back. Pairs with {@link readAccountLinkCallback} and
|
|
5298
|
+
* {@link linkAccountWithGrant}.
|
|
5299
|
+
*
|
|
5300
|
+
* This exists because a browser app is in a bind: it holds an account root and
|
|
5301
|
+
* can never hold a *first* cloud session, since only Google issues one. So the
|
|
5302
|
+
* person goes to the cloud, where they are signed in, and consents there. What
|
|
5303
|
+
* comes back is a grant — consent to link this one account, spendable only by
|
|
5304
|
+
* whoever can sign with its root.
|
|
5305
|
+
*
|
|
5306
|
+
* @param callbackUrl where the portal sends the person back. Must be an origin
|
|
5307
|
+
* the cloud allows; unlisted ones are refused when the grant is minted, not
|
|
5308
|
+
* here. The grant arrives in the URL **fragment**, which browsers do not
|
|
5309
|
+
* send to servers.
|
|
5310
|
+
*
|
|
5311
|
+
* Static, so it needs no client and no session: there is nothing to
|
|
5312
|
+
* authenticate as yet.
|
|
5313
|
+
*/
|
|
5314
|
+
static accountLinkHandoff(options) {
|
|
5315
|
+
const portal = options.portalUrl.replace(/\/+$/, "");
|
|
5316
|
+
const query = new URLSearchParams({
|
|
5317
|
+
"link-account": options.accountId,
|
|
5318
|
+
"callback-url": options.callbackUrl
|
|
5319
|
+
});
|
|
5320
|
+
return { url: `${portal}/?${query.toString()}`, accountId: options.accountId };
|
|
5321
|
+
}
|
|
5322
|
+
/**
|
|
5323
|
+
* Read the portal's answer out of a callback URL's fragment.
|
|
5324
|
+
*
|
|
5325
|
+
* Returns `{}` when there is nothing to read, so it is safe to call on every
|
|
5326
|
+
* load — which is how a redirected app finds out it has been sent back.
|
|
5327
|
+
*
|
|
5328
|
+
* @param href defaults to the current location, when there is one.
|
|
5329
|
+
*/
|
|
5330
|
+
static readAccountLinkCallback(href) {
|
|
5331
|
+
const source = href ?? (typeof window === "undefined" ? "" : window.location.href);
|
|
5332
|
+
if (!source) return {};
|
|
5333
|
+
let hash;
|
|
5334
|
+
try {
|
|
5335
|
+
hash = new URL(source).hash;
|
|
5336
|
+
} catch {
|
|
5337
|
+
return {};
|
|
5338
|
+
}
|
|
5339
|
+
const params = new URLSearchParams(hash.replace(/^#/, ""));
|
|
5340
|
+
const grant = params.get("grant");
|
|
5341
|
+
const accountId = params.get("account");
|
|
5342
|
+
const error = params.get("error");
|
|
5343
|
+
const out = {};
|
|
5344
|
+
if (grant) out.grant = grant;
|
|
5345
|
+
if (accountId) out.accountId = accountId;
|
|
5346
|
+
if (error) out.error = error;
|
|
5347
|
+
return out;
|
|
5348
|
+
}
|
|
5349
|
+
/**
|
|
5350
|
+
* Spend a link grant: sign it with the account root and post the pair.
|
|
5351
|
+
*
|
|
5352
|
+
* Anonymous, and it has to be — the app doing this holds no cloud session,
|
|
5353
|
+
* which is the whole reason the grant exists. The grant carries the consenting
|
|
5354
|
+
* login sealed inside it, so nothing here names one; a caller-supplied email
|
|
5355
|
+
* would be a field to lie in.
|
|
5356
|
+
*
|
|
5357
|
+
* The signature is an ordinary account-link signature with the grant as the
|
|
5358
|
+
* nonce, so the same {@link signAccountLink} every other link path uses signs
|
|
5359
|
+
* this one. Both halves are required: a grant without the key links nothing,
|
|
5360
|
+
* which is what makes it safe to carry through a browser redirect.
|
|
5361
|
+
*
|
|
5362
|
+
* A `403` means the grant was bad, expired, already spent, or signed by a key
|
|
5363
|
+
* that names a different account; `409` that the account belongs to another
|
|
5364
|
+
* login; `402` that the plan is full.
|
|
5365
|
+
*/
|
|
5366
|
+
async linkAccountWithGrant(options) {
|
|
5367
|
+
const root = await accountRootFromSecret(options.rootSecret);
|
|
5368
|
+
const body = await this.request(
|
|
5369
|
+
"POST",
|
|
5370
|
+
"/api/cloud/accounts/link",
|
|
5371
|
+
{
|
|
5372
|
+
body: {
|
|
5373
|
+
grant: options.grant,
|
|
5374
|
+
root_public_key: root.publicKey,
|
|
5375
|
+
signature: await signAccountLink({
|
|
5376
|
+
rootSecret: options.rootSecret,
|
|
5377
|
+
nonce: options.grant
|
|
5378
|
+
})
|
|
5379
|
+
},
|
|
5380
|
+
anonymous: true
|
|
5381
|
+
}
|
|
5382
|
+
);
|
|
5383
|
+
return {
|
|
5384
|
+
accountId: String(body.account_id ?? root.accountId),
|
|
5385
|
+
linkedAt: body.linked_at ?? null,
|
|
5386
|
+
alreadyLinked: body.already_linked === true
|
|
5387
|
+
};
|
|
5388
|
+
}
|
|
5280
5389
|
/** The accounts linked to this login, and how many the plan allows. */
|
|
5281
5390
|
async getMyAccounts() {
|
|
5282
5391
|
const body = await this.request("GET", "/api/cloud/me/accounts");
|