@tinycloud/sdk-core 2.11.0-beta.1 → 2.11.0-beta.4
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/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +76 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -10
- package/dist/index.d.ts +55 -10
- package/dist/index.js +76 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6702,15 +6702,28 @@ function normalizeSpace(space) {
|
|
|
6702
6702
|
function isCapabilitySubset(requested, granted) {
|
|
6703
6703
|
const missing = [];
|
|
6704
6704
|
for (const req of requested) {
|
|
6705
|
-
const
|
|
6706
|
-
|
|
6705
|
+
const matchingScope = granted.filter(
|
|
6706
|
+
(entry) => canonicalizeEntryScopeMatches(req, entry)
|
|
6707
|
+
);
|
|
6708
|
+
const requestedActions = expandActionShortNames(
|
|
6709
|
+
req.service,
|
|
6710
|
+
req.actions
|
|
6711
|
+
);
|
|
6712
|
+
const grantedActions = matchingScope.flatMap(
|
|
6713
|
+
(entry) => expandActionShortNames(entry.service, entry.actions)
|
|
6714
|
+
);
|
|
6715
|
+
const covered = requestedActions.every(
|
|
6716
|
+
(requestedAction) => grantedActions.some(
|
|
6717
|
+
(grantedAction) => actionContains(grantedAction, requestedAction)
|
|
6718
|
+
)
|
|
6719
|
+
);
|
|
6720
|
+
if (!covered) {
|
|
6707
6721
|
missing.push(cloneEntry(req));
|
|
6708
|
-
continue;
|
|
6709
6722
|
}
|
|
6710
6723
|
}
|
|
6711
6724
|
return { subset: missing.length === 0, missing };
|
|
6712
6725
|
}
|
|
6713
|
-
function
|
|
6726
|
+
function canonicalizeEntryScopeMatches(requested, granted) {
|
|
6714
6727
|
if (requested.service !== granted.service) {
|
|
6715
6728
|
return false;
|
|
6716
6729
|
}
|
|
@@ -6720,15 +6733,6 @@ function canonicalizeEntryMatches(requested, granted) {
|
|
|
6720
6733
|
if (!pathContains2(granted.path, requested.path)) {
|
|
6721
6734
|
return false;
|
|
6722
6735
|
}
|
|
6723
|
-
const reqActions = new Set(
|
|
6724
|
-
expandActionShortNames(requested.service, requested.actions)
|
|
6725
|
-
);
|
|
6726
|
-
const grantedActions = expandActionShortNames(granted.service, granted.actions);
|
|
6727
|
-
for (const a of reqActions) {
|
|
6728
|
-
if (!grantedActions.some((grantedAction) => actionContains(grantedAction, a))) {
|
|
6729
|
-
return false;
|
|
6730
|
-
}
|
|
6731
|
-
}
|
|
6732
6736
|
if (!recapCaveatsEqual(requested.caveats, granted.caveats)) {
|
|
6733
6737
|
return false;
|
|
6734
6738
|
}
|
|
@@ -12120,6 +12124,22 @@ var ACCOUNT_SPACES_PATH = "spaces/";
|
|
|
12120
12124
|
var AccountService = class {
|
|
12121
12125
|
constructor(config) {
|
|
12122
12126
|
this.config = config;
|
|
12127
|
+
/**
|
|
12128
|
+
* Per-account-space memo for {@link ensureAccountIndex}.
|
|
12129
|
+
*
|
|
12130
|
+
* Applying the index migration is a no-op once the schema exists, but the
|
|
12131
|
+
* SQL service still spends two round trips discovering that (create the
|
|
12132
|
+
* migrations table, then read the applied-migration rows). Account bootstrap
|
|
12133
|
+
* touches the index eight times, so without a memo that is ~14 wasted
|
|
12134
|
+
* requests on the cold sign-in path. The in-flight dedupe inside SQLService
|
|
12135
|
+
* never helps here: the node SDK builds a fresh SQLService per
|
|
12136
|
+
* `getAccountDb()` call, so its lock map is always empty.
|
|
12137
|
+
*
|
|
12138
|
+
* Keyed by account space id, so a different account never reuses this entry.
|
|
12139
|
+
* Failures are evicted so a later call retries instead of inheriting a
|
|
12140
|
+
* permanently poisoned result.
|
|
12141
|
+
*/
|
|
12142
|
+
this.accountIndexReady = /* @__PURE__ */ new Map();
|
|
12123
12143
|
this.applications = {
|
|
12124
12144
|
list: async (options2 = {}) => {
|
|
12125
12145
|
if (options2.preferIndex) {
|
|
@@ -12153,7 +12173,7 @@ var AccountService = class {
|
|
|
12153
12173
|
if (!loaded.ok) return accountErr(loaded.error);
|
|
12154
12174
|
return (0, import_sdk_services6.ok)(applicationFromRecord(key, loaded.data.data));
|
|
12155
12175
|
},
|
|
12156
|
-
register: async (manifest) => {
|
|
12176
|
+
register: async (manifest, options2 = {}) => {
|
|
12157
12177
|
const manifests = Array.isArray(manifest) ? manifest : [manifest];
|
|
12158
12178
|
const request = composeManifestRequest(manifests);
|
|
12159
12179
|
if (request.registryRecords.length === 0) {
|
|
@@ -12171,7 +12191,7 @@ var AccountService = class {
|
|
|
12171
12191
|
let registered;
|
|
12172
12192
|
for (const record of request.registryRecords) {
|
|
12173
12193
|
const manifestHash = hashJson(record.manifests);
|
|
12174
|
-
if (await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
12194
|
+
if (!options2.assumeUnregistered && await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
12175
12195
|
registered = {
|
|
12176
12196
|
appId: record.app_id,
|
|
12177
12197
|
manifests: record.manifests,
|
|
@@ -12352,6 +12372,7 @@ var AccountService = class {
|
|
|
12352
12372
|
const delegations = await this.delegations.list();
|
|
12353
12373
|
if (!delegations.ok) return delegations;
|
|
12354
12374
|
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12375
|
+
this.invalidateAccountIndexMemo();
|
|
12355
12376
|
const schema = await this.ensureAccountIndex(dbResult.data);
|
|
12356
12377
|
if (!schema.ok) return schema;
|
|
12357
12378
|
const statements = [
|
|
@@ -12751,7 +12772,41 @@ var AccountService = class {
|
|
|
12751
12772
|
]);
|
|
12752
12773
|
});
|
|
12753
12774
|
}
|
|
12775
|
+
/**
|
|
12776
|
+
* Apply the account index schema at most once per account space.
|
|
12777
|
+
*
|
|
12778
|
+
* The index is a cache over canonical KV state, and every caller already
|
|
12779
|
+
* tolerates it being absent (`ignoreIndexFailure` / `isMissingIndexError`),
|
|
12780
|
+
* so a memo that is wrong in the "already applied" direction degrades to a
|
|
12781
|
+
* `no such table` read that the caller handles. A memo that is wrong in the
|
|
12782
|
+
* other direction would be a real bug, so failures are never cached.
|
|
12783
|
+
*/
|
|
12754
12784
|
async ensureAccountIndex(db) {
|
|
12785
|
+
const key = this.config.getAccountSpaceId() ?? "";
|
|
12786
|
+
const cached = this.accountIndexReady.get(key);
|
|
12787
|
+
if (cached) return cached;
|
|
12788
|
+
const pending = this.applyAccountIndex(db);
|
|
12789
|
+
this.accountIndexReady.set(key, pending);
|
|
12790
|
+
const evict = () => {
|
|
12791
|
+
if (this.accountIndexReady.get(key) === pending) {
|
|
12792
|
+
this.accountIndexReady.delete(key);
|
|
12793
|
+
}
|
|
12794
|
+
};
|
|
12795
|
+
let settled;
|
|
12796
|
+
try {
|
|
12797
|
+
settled = await pending;
|
|
12798
|
+
} catch (error) {
|
|
12799
|
+
evict();
|
|
12800
|
+
throw error;
|
|
12801
|
+
}
|
|
12802
|
+
if (!settled.ok) evict();
|
|
12803
|
+
return settled;
|
|
12804
|
+
}
|
|
12805
|
+
/** Drop the memo so the next {@link ensureAccountIndex} re-applies the schema. */
|
|
12806
|
+
invalidateAccountIndexMemo() {
|
|
12807
|
+
this.accountIndexReady.delete(this.config.getAccountSpaceId() ?? "");
|
|
12808
|
+
}
|
|
12809
|
+
async applyAccountIndex(db) {
|
|
12755
12810
|
const migrated = await db.migrations.apply({
|
|
12756
12811
|
namespace: ACCOUNT_INDEX_NAMESPACE,
|
|
12757
12812
|
migrations: [
|
|
@@ -15295,13 +15350,14 @@ async function discoverLocalTinyCloudNode(options2 = {}) {
|
|
|
15295
15350
|
}
|
|
15296
15351
|
const fetchFn = options2.fetch ?? globalThis.fetch;
|
|
15297
15352
|
const identityStore = options2.identityStore ?? defaultLocalNodeIdentityStore;
|
|
15298
|
-
const staticCandidates = [
|
|
15299
|
-
|
|
15353
|
+
const staticCandidates = [];
|
|
15354
|
+
if (options2.localNodeUrl) {
|
|
15355
|
+
staticCandidates.push({
|
|
15300
15356
|
source: "local-loopback",
|
|
15301
|
-
url: options2.localNodeUrl
|
|
15357
|
+
url: options2.localNodeUrl,
|
|
15302
15358
|
timeoutMs: LOCAL_LOOPBACK_PROBE_TIMEOUT_MS
|
|
15303
|
-
}
|
|
15304
|
-
|
|
15359
|
+
});
|
|
15360
|
+
}
|
|
15305
15361
|
if (options2.localLinkName) {
|
|
15306
15362
|
if (isValidDnsLabel(options2.localLinkName)) {
|
|
15307
15363
|
staticCandidates.push({
|