@tinycloud/sdk-core 2.11.0-beta.3 → 2.11.0-beta.5
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/index.cjs +112 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -7
- package/dist/index.d.ts +35 -7
- package/dist/index.js +116 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -2487,6 +2487,13 @@ interface AccountSpace {
|
|
|
2487
2487
|
updatedAt?: string;
|
|
2488
2488
|
expiresAt?: Date;
|
|
2489
2489
|
}
|
|
2490
|
+
interface RegisterBatchSuccess {
|
|
2491
|
+
spaces: AccountSpace[];
|
|
2492
|
+
/** Present iff the batch write failed ambiguously and per-space
|
|
2493
|
+
* reconciliation recovered it. The original batch error verbatim, so
|
|
2494
|
+
* callers can record the degradation structurally (TC-361). */
|
|
2495
|
+
recoveredFromBatchError?: ServiceError;
|
|
2496
|
+
}
|
|
2490
2497
|
interface AccountDelegation {
|
|
2491
2498
|
cid: string;
|
|
2492
2499
|
direction: "granted" | "received";
|
|
@@ -2591,6 +2598,17 @@ declare class AccountService {
|
|
|
2591
2598
|
list: (options?: AccountSpaceListOptions) => Promise<Result<AccountSpace[]>>;
|
|
2592
2599
|
get: (spaceId: string) => Promise<Result<AccountSpace>>;
|
|
2593
2600
|
register: (space: SpaceInfo | AccountSpace) => Promise<Result<AccountSpace>>;
|
|
2601
|
+
/**
|
|
2602
|
+
* Register multiple spaces in one KV batch write + one multi-row index
|
|
2603
|
+
* write, instead of one `register()` round trip per space (TC-373).
|
|
2604
|
+
*
|
|
2605
|
+
* The stored records are computed exactly once and reused for both the
|
|
2606
|
+
* batch attempt and any reconciliation below, so a fallback never mints a
|
|
2607
|
+
* fresh timestamp for a space that already has a written record — a
|
|
2608
|
+
* second `spaceRecordFromInput` call would produce a new content hash and
|
|
2609
|
+
* leave the first attempt's blocks orphaned.
|
|
2610
|
+
*/
|
|
2611
|
+
registerBatch: (spaces: readonly (SpaceInfo | AccountSpace)[]) => Promise<Result<RegisterBatchSuccess>>;
|
|
2594
2612
|
syncAccessible: () => Promise<Result<AccountSpace[]>>;
|
|
2595
2613
|
remove: (spaceId: string) => Promise<Result<void>>;
|
|
2596
2614
|
};
|
|
@@ -2623,6 +2641,16 @@ declare class AccountService {
|
|
|
2623
2641
|
private deleteApplicationIndex;
|
|
2624
2642
|
private upsertSpaceIndexQuietly;
|
|
2625
2643
|
private upsertSpaceIndex;
|
|
2644
|
+
private upsertSpacesIndexQuietly;
|
|
2645
|
+
/**
|
|
2646
|
+
* Upsert multiple space index rows in ONE multi-row `INSERT OR REPLACE`
|
|
2647
|
+
* statement (TC-373), rather than one statement per space. This matters
|
|
2648
|
+
* because `IDatabaseHandle.batch()` executes its statement list as a plain
|
|
2649
|
+
* loop, not a single database transaction — an N-statement batch is not
|
|
2650
|
+
* atomic. A single multi-row INSERT is one SQLite statement, so it applies
|
|
2651
|
+
* atomically: all rows or none.
|
|
2652
|
+
*/
|
|
2653
|
+
private upsertSpacesIndex;
|
|
2626
2654
|
private deleteSpaceIndexQuietly;
|
|
2627
2655
|
private deleteSpaceIndex;
|
|
2628
2656
|
private resolveSpace;
|
|
@@ -2776,7 +2804,7 @@ interface LocationRecord extends LocationRecordPayload {
|
|
|
2776
2804
|
type LocationSource = "explicit" | "local-loopback" | "local-link" | "blockchain" | "centralized" | "fallback";
|
|
2777
2805
|
declare const DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
2778
2806
|
declare const DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
2779
|
-
/**
|
|
2807
|
+
/** Conventional local loopback node URL. Probed only when explicitly configured. */
|
|
2780
2808
|
declare const DEFAULT_LOCAL_NODE_URL = "http://127.0.0.1:8000";
|
|
2781
2809
|
/** Probe timeout for the local loopback candidate. No retries. */
|
|
2782
2810
|
declare const LOCAL_LOOPBACK_PROBE_TIMEOUT_MS = 250;
|
|
@@ -2863,7 +2891,7 @@ interface DiscoverLocalTinyCloudNodeOptions {
|
|
|
2863
2891
|
subject?: string;
|
|
2864
2892
|
/** Enable local-node auto-discovery. Default true. */
|
|
2865
2893
|
autoDiscoverLocalNode?: boolean;
|
|
2866
|
-
/** Local loopback node URL to probe.
|
|
2894
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
2867
2895
|
localNodeUrl?: string;
|
|
2868
2896
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
2869
2897
|
localLinkName?: string;
|
|
@@ -2897,12 +2925,12 @@ interface ResolveTinyCloudHostsOptions {
|
|
|
2897
2925
|
/** Verify centralized/blockchain record signatures. Default true. */
|
|
2898
2926
|
verifyRecords?: boolean;
|
|
2899
2927
|
/**
|
|
2900
|
-
* Probe
|
|
2901
|
-
* registry/hosted resolution. Default true.
|
|
2902
|
-
*
|
|
2928
|
+
* Probe configured and registered local TinyCloud node endpoints before
|
|
2929
|
+
* falling back to registry/hosted resolution. Default true. The loopback
|
|
2930
|
+
* URL is probed only when `localNodeUrl` is explicitly configured.
|
|
2903
2931
|
*/
|
|
2904
2932
|
autoDiscoverLocalNode?: boolean;
|
|
2905
|
-
/** Local loopback node URL to probe.
|
|
2933
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
2906
2934
|
localNodeUrl?: string;
|
|
2907
2935
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
2908
2936
|
localLinkName?: string;
|
|
@@ -2988,4 +3016,4 @@ declare const EXPIRY: {
|
|
|
2988
3016
|
declare const DEFAULT_SIGNED_READ_URL_EXPIRY_MS: number;
|
|
2989
3017
|
type ExpiryTier = keyof typeof EXPIRY;
|
|
2990
3018
|
|
|
2991
|
-
export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, type AbilitiesMap, type AccountApplication, type AccountApplicationListOptions, type AccountApplicationRegisterOptions, type AccountDelegation, type AccountDelegationListOptions, AccountDelegationPage, AccountDelegationQueryOptions, type AccountDelegationRevokeOptions, type AccountIndexEnsureResult, type AccountIndexRebuildResult, type AccountIndexStatus, type AccountIndexedReadOptions, AccountService, type AccountServiceConfig, type AccountSpace, type AccountSpaceListOptions, type AccountStatus, AutoApproveSpaceCreationHandler, type AutoRejectStrategy, type AutoSignStrategy, type Bytes, type CallbackStrategy, type CanonicalAddress, type CanonicalParsedNetworkId, CaveatedDelegationUnsupportedError, type ClientSession, ClientSessionSchema, CloudLocationResolutionError, type ComposeManifestOptions, type ComposedManifestRequest, type CreateDelegationFunction, CreateDelegationParams, DEFAULT_DEFAULTS, DEFAULT_EXPIRY, DEFAULT_KNOWLEDGE_ROOT, DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY, DEFAULT_LOCAL_NODE_URL, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DEFAULT_TINYCLOUD_FALLBACK_HOST, DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL, Delegation, DelegationManager, DelegationRevocationReceipt, type DidCacheKeyOptions, type DidEqualsOptions, type DiscoverLocalTinyCloudNodeOptions, type DiscoveredLocalTinyCloudNode, ENCRYPTION_MANIFEST_SPACE, ENCRYPTION_PERMISSION_SERVICE, EXPIRY, type EnsData, EnsDataSchema, type EventEmitterStrategy, type ExpiryTier, type Extension, GenerateShareParams, ICapabilityKeyRegistry, type IENSResolver, type INotificationHandler, type ISessionManager, type ISessionStorage, ISharingService, type ISigner, type ISpace, type ISpaceCreationHandler, type ISpaceScopedDelegations, type ISpaceScopedSharing, type ISpaceService, type IUserAuthorization, type IWasmBindings, IdentityParseError, LOCAL_LINK_HOST_SUFFIX, LOCAL_LINK_PROBE_TIMEOUT_MS, LOCAL_LOOPBACK_PROBE_TIMEOUT_MS, type LocalNodeIdentityStore, type LocationCandidate, type LocationCandidateInput, type LocationRecord, type LocationRecordPayload, type LocationRecordSigner, LocationRecordValidationError, type LocationResolutionAttempt, type LocationSource, type Manifest, type ManifestDefaults, type ManifestKnowledge, type ManifestRegistryRecord, type ManifestSecretActions, ManifestValidationError, type NodeInfo, type OpenKeyCallbackStrategy, type OpenKeySigningRequestBody, type OpenKeySigningResponseBody, type OpenKeySigningStrategyOptions, type ParseRecapFromSiwe, type PartialSiweMessage, type PermissionEntry, PermissionNotInManifestError, type PersistedSessionData, type PersistedSessionProof, type PersistedTinyCloudSession, type PkhDidParts, ProtocolMismatchError, type ResolveCloudLocationOptions, type ResolveTinyCloudHostsOptions, type ResolvedCapabilities, type ResolvedCloudLocation, type ResolvedDelegate, type ResolvedTinyCloudHosts, type ResourceCapability, SECRETS_SPACE, SERVICE_LONG_TO_SHORT, SERVICE_SHORT_TO_LONG, type ServerHost, SessionExpiredError, ShareLink, type SignCallback, type SignInOptions, type SignRequest, type SignResponse, type SignStrategy, SilentNotificationHandler, type SiweConfig, SiweConfigSchema, Space, type SpaceAbilitiesMap, type SpaceConfig, type SpaceCreationContext, type SpaceDelegationParams, type SpaceErrorCode, SpaceErrorCodes, type SpaceHostResult, SpaceInfo, SpaceService, type SpaceServiceConfig, type SubsetCheckResult, TinyCloud, type TinyCloudConfig, type TinyCloudSession, UnsupportedFeatureError, type UserAuthorizationConfig, VAULT_PERMISSION_SERVICE, type ValidatedPersistedSessionProof, type ValidationError, VersionCheckError, type WasmRecapEntry, type WebStorageLike, actionContains, activateSessionWithHost, addressStorageKey, applyPrefix, buildSpaceUri, canonicalLocationPayload, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeRecapCaveats, checkNodeInfo, composeManifestRequest, createInMemoryLocalNodeIdentityStore, createLocalStorageLocalNodeIdentityStore, createOpenKeyCallbackSigningStrategy, createSpaceService, defaultSignStrategy, defaultSpaceCreationHandler, didCacheKey, didEquals, discoverLocalTinyCloudNode, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, fetchLocationRecord, fetchPeerId, httpUrlToMultiaddr, isCapabilitySubset, isEvmAddress, loadManifest, locationPayloadForRecord, makePkhSpaceId, makePublicSpaceId, manifestAbilitiesUnion, multiaddrToHttpUrl, normalizeDefaults, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseRecapCapabilities, parseSpaceUri, pkhDid, principalDid, principalDidEquals, recapCaveatsEqual, resolveCloudLocation, resolveManifest, resolveManifestKnowledgeRoot, resolveTinyCloudHosts, resourceCapabilitiesToAbilitiesMap, resourceCapabilitiesToSpaceAbilitiesMap, signLocationRecord, submitHostDelegation, validateClientSession, validateLocationRecord, validateLocationRecordPayload, validateManifest, validatePersistedSessionData, verifyDidKeyEd25519Signature, verifyLocationRecord };
|
|
3019
|
+
export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, type AbilitiesMap, type AccountApplication, type AccountApplicationListOptions, type AccountApplicationRegisterOptions, type AccountDelegation, type AccountDelegationListOptions, AccountDelegationPage, AccountDelegationQueryOptions, type AccountDelegationRevokeOptions, type AccountIndexEnsureResult, type AccountIndexRebuildResult, type AccountIndexStatus, type AccountIndexedReadOptions, AccountService, type AccountServiceConfig, type AccountSpace, type AccountSpaceListOptions, type AccountStatus, AutoApproveSpaceCreationHandler, type AutoRejectStrategy, type AutoSignStrategy, type Bytes, type CallbackStrategy, type CanonicalAddress, type CanonicalParsedNetworkId, CaveatedDelegationUnsupportedError, type ClientSession, ClientSessionSchema, CloudLocationResolutionError, type ComposeManifestOptions, type ComposedManifestRequest, type CreateDelegationFunction, CreateDelegationParams, DEFAULT_DEFAULTS, DEFAULT_EXPIRY, DEFAULT_KNOWLEDGE_ROOT, DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY, DEFAULT_LOCAL_NODE_URL, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DEFAULT_TINYCLOUD_FALLBACK_HOST, DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL, Delegation, DelegationManager, DelegationRevocationReceipt, type DidCacheKeyOptions, type DidEqualsOptions, type DiscoverLocalTinyCloudNodeOptions, type DiscoveredLocalTinyCloudNode, ENCRYPTION_MANIFEST_SPACE, ENCRYPTION_PERMISSION_SERVICE, EXPIRY, type EnsData, EnsDataSchema, type EventEmitterStrategy, type ExpiryTier, type Extension, GenerateShareParams, ICapabilityKeyRegistry, type IENSResolver, type INotificationHandler, type ISessionManager, type ISessionStorage, ISharingService, type ISigner, type ISpace, type ISpaceCreationHandler, type ISpaceScopedDelegations, type ISpaceScopedSharing, type ISpaceService, type IUserAuthorization, type IWasmBindings, IdentityParseError, LOCAL_LINK_HOST_SUFFIX, LOCAL_LINK_PROBE_TIMEOUT_MS, LOCAL_LOOPBACK_PROBE_TIMEOUT_MS, type LocalNodeIdentityStore, type LocationCandidate, type LocationCandidateInput, type LocationRecord, type LocationRecordPayload, type LocationRecordSigner, LocationRecordValidationError, type LocationResolutionAttempt, type LocationSource, type Manifest, type ManifestDefaults, type ManifestKnowledge, type ManifestRegistryRecord, type ManifestSecretActions, ManifestValidationError, type NodeInfo, type OpenKeyCallbackStrategy, type OpenKeySigningRequestBody, type OpenKeySigningResponseBody, type OpenKeySigningStrategyOptions, type ParseRecapFromSiwe, type PartialSiweMessage, type PermissionEntry, PermissionNotInManifestError, type PersistedSessionData, type PersistedSessionProof, type PersistedTinyCloudSession, type PkhDidParts, ProtocolMismatchError, type RegisterBatchSuccess, type ResolveCloudLocationOptions, type ResolveTinyCloudHostsOptions, type ResolvedCapabilities, type ResolvedCloudLocation, type ResolvedDelegate, type ResolvedTinyCloudHosts, type ResourceCapability, SECRETS_SPACE, SERVICE_LONG_TO_SHORT, SERVICE_SHORT_TO_LONG, type ServerHost, SessionExpiredError, ShareLink, type SignCallback, type SignInOptions, type SignRequest, type SignResponse, type SignStrategy, SilentNotificationHandler, type SiweConfig, SiweConfigSchema, Space, type SpaceAbilitiesMap, type SpaceConfig, type SpaceCreationContext, type SpaceDelegationParams, type SpaceErrorCode, SpaceErrorCodes, type SpaceHostResult, SpaceInfo, SpaceService, type SpaceServiceConfig, type SubsetCheckResult, TinyCloud, type TinyCloudConfig, type TinyCloudSession, UnsupportedFeatureError, type UserAuthorizationConfig, VAULT_PERMISSION_SERVICE, type ValidatedPersistedSessionProof, type ValidationError, VersionCheckError, type WasmRecapEntry, type WebStorageLike, actionContains, activateSessionWithHost, addressStorageKey, applyPrefix, buildSpaceUri, canonicalLocationPayload, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeRecapCaveats, checkNodeInfo, composeManifestRequest, createInMemoryLocalNodeIdentityStore, createLocalStorageLocalNodeIdentityStore, createOpenKeyCallbackSigningStrategy, createSpaceService, defaultSignStrategy, defaultSpaceCreationHandler, didCacheKey, didEquals, discoverLocalTinyCloudNode, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, fetchLocationRecord, fetchPeerId, httpUrlToMultiaddr, isCapabilitySubset, isEvmAddress, loadManifest, locationPayloadForRecord, makePkhSpaceId, makePublicSpaceId, manifestAbilitiesUnion, multiaddrToHttpUrl, normalizeDefaults, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseRecapCapabilities, parseSpaceUri, pkhDid, principalDid, principalDidEquals, recapCaveatsEqual, resolveCloudLocation, resolveManifest, resolveManifestKnowledgeRoot, resolveTinyCloudHosts, resourceCapabilitiesToAbilitiesMap, resourceCapabilitiesToSpaceAbilitiesMap, signLocationRecord, submitHostDelegation, validateClientSession, validateLocationRecord, validateLocationRecordPayload, validateManifest, validatePersistedSessionData, verifyDidKeyEd25519Signature, verifyLocationRecord };
|
package/dist/index.d.ts
CHANGED
|
@@ -2487,6 +2487,13 @@ interface AccountSpace {
|
|
|
2487
2487
|
updatedAt?: string;
|
|
2488
2488
|
expiresAt?: Date;
|
|
2489
2489
|
}
|
|
2490
|
+
interface RegisterBatchSuccess {
|
|
2491
|
+
spaces: AccountSpace[];
|
|
2492
|
+
/** Present iff the batch write failed ambiguously and per-space
|
|
2493
|
+
* reconciliation recovered it. The original batch error verbatim, so
|
|
2494
|
+
* callers can record the degradation structurally (TC-361). */
|
|
2495
|
+
recoveredFromBatchError?: ServiceError;
|
|
2496
|
+
}
|
|
2490
2497
|
interface AccountDelegation {
|
|
2491
2498
|
cid: string;
|
|
2492
2499
|
direction: "granted" | "received";
|
|
@@ -2591,6 +2598,17 @@ declare class AccountService {
|
|
|
2591
2598
|
list: (options?: AccountSpaceListOptions) => Promise<Result<AccountSpace[]>>;
|
|
2592
2599
|
get: (spaceId: string) => Promise<Result<AccountSpace>>;
|
|
2593
2600
|
register: (space: SpaceInfo | AccountSpace) => Promise<Result<AccountSpace>>;
|
|
2601
|
+
/**
|
|
2602
|
+
* Register multiple spaces in one KV batch write + one multi-row index
|
|
2603
|
+
* write, instead of one `register()` round trip per space (TC-373).
|
|
2604
|
+
*
|
|
2605
|
+
* The stored records are computed exactly once and reused for both the
|
|
2606
|
+
* batch attempt and any reconciliation below, so a fallback never mints a
|
|
2607
|
+
* fresh timestamp for a space that already has a written record — a
|
|
2608
|
+
* second `spaceRecordFromInput` call would produce a new content hash and
|
|
2609
|
+
* leave the first attempt's blocks orphaned.
|
|
2610
|
+
*/
|
|
2611
|
+
registerBatch: (spaces: readonly (SpaceInfo | AccountSpace)[]) => Promise<Result<RegisterBatchSuccess>>;
|
|
2594
2612
|
syncAccessible: () => Promise<Result<AccountSpace[]>>;
|
|
2595
2613
|
remove: (spaceId: string) => Promise<Result<void>>;
|
|
2596
2614
|
};
|
|
@@ -2623,6 +2641,16 @@ declare class AccountService {
|
|
|
2623
2641
|
private deleteApplicationIndex;
|
|
2624
2642
|
private upsertSpaceIndexQuietly;
|
|
2625
2643
|
private upsertSpaceIndex;
|
|
2644
|
+
private upsertSpacesIndexQuietly;
|
|
2645
|
+
/**
|
|
2646
|
+
* Upsert multiple space index rows in ONE multi-row `INSERT OR REPLACE`
|
|
2647
|
+
* statement (TC-373), rather than one statement per space. This matters
|
|
2648
|
+
* because `IDatabaseHandle.batch()` executes its statement list as a plain
|
|
2649
|
+
* loop, not a single database transaction — an N-statement batch is not
|
|
2650
|
+
* atomic. A single multi-row INSERT is one SQLite statement, so it applies
|
|
2651
|
+
* atomically: all rows or none.
|
|
2652
|
+
*/
|
|
2653
|
+
private upsertSpacesIndex;
|
|
2626
2654
|
private deleteSpaceIndexQuietly;
|
|
2627
2655
|
private deleteSpaceIndex;
|
|
2628
2656
|
private resolveSpace;
|
|
@@ -2776,7 +2804,7 @@ interface LocationRecord extends LocationRecordPayload {
|
|
|
2776
2804
|
type LocationSource = "explicit" | "local-loopback" | "local-link" | "blockchain" | "centralized" | "fallback";
|
|
2777
2805
|
declare const DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
2778
2806
|
declare const DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
2779
|
-
/**
|
|
2807
|
+
/** Conventional local loopback node URL. Probed only when explicitly configured. */
|
|
2780
2808
|
declare const DEFAULT_LOCAL_NODE_URL = "http://127.0.0.1:8000";
|
|
2781
2809
|
/** Probe timeout for the local loopback candidate. No retries. */
|
|
2782
2810
|
declare const LOCAL_LOOPBACK_PROBE_TIMEOUT_MS = 250;
|
|
@@ -2863,7 +2891,7 @@ interface DiscoverLocalTinyCloudNodeOptions {
|
|
|
2863
2891
|
subject?: string;
|
|
2864
2892
|
/** Enable local-node auto-discovery. Default true. */
|
|
2865
2893
|
autoDiscoverLocalNode?: boolean;
|
|
2866
|
-
/** Local loopback node URL to probe.
|
|
2894
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
2867
2895
|
localNodeUrl?: string;
|
|
2868
2896
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
2869
2897
|
localLinkName?: string;
|
|
@@ -2897,12 +2925,12 @@ interface ResolveTinyCloudHostsOptions {
|
|
|
2897
2925
|
/** Verify centralized/blockchain record signatures. Default true. */
|
|
2898
2926
|
verifyRecords?: boolean;
|
|
2899
2927
|
/**
|
|
2900
|
-
* Probe
|
|
2901
|
-
* registry/hosted resolution. Default true.
|
|
2902
|
-
*
|
|
2928
|
+
* Probe configured and registered local TinyCloud node endpoints before
|
|
2929
|
+
* falling back to registry/hosted resolution. Default true. The loopback
|
|
2930
|
+
* URL is probed only when `localNodeUrl` is explicitly configured.
|
|
2903
2931
|
*/
|
|
2904
2932
|
autoDiscoverLocalNode?: boolean;
|
|
2905
|
-
/** Local loopback node URL to probe.
|
|
2933
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
2906
2934
|
localNodeUrl?: string;
|
|
2907
2935
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
2908
2936
|
localLinkName?: string;
|
|
@@ -2988,4 +3016,4 @@ declare const EXPIRY: {
|
|
|
2988
3016
|
declare const DEFAULT_SIGNED_READ_URL_EXPIRY_MS: number;
|
|
2989
3017
|
type ExpiryTier = keyof typeof EXPIRY;
|
|
2990
3018
|
|
|
2991
|
-
export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, type AbilitiesMap, type AccountApplication, type AccountApplicationListOptions, type AccountApplicationRegisterOptions, type AccountDelegation, type AccountDelegationListOptions, AccountDelegationPage, AccountDelegationQueryOptions, type AccountDelegationRevokeOptions, type AccountIndexEnsureResult, type AccountIndexRebuildResult, type AccountIndexStatus, type AccountIndexedReadOptions, AccountService, type AccountServiceConfig, type AccountSpace, type AccountSpaceListOptions, type AccountStatus, AutoApproveSpaceCreationHandler, type AutoRejectStrategy, type AutoSignStrategy, type Bytes, type CallbackStrategy, type CanonicalAddress, type CanonicalParsedNetworkId, CaveatedDelegationUnsupportedError, type ClientSession, ClientSessionSchema, CloudLocationResolutionError, type ComposeManifestOptions, type ComposedManifestRequest, type CreateDelegationFunction, CreateDelegationParams, DEFAULT_DEFAULTS, DEFAULT_EXPIRY, DEFAULT_KNOWLEDGE_ROOT, DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY, DEFAULT_LOCAL_NODE_URL, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DEFAULT_TINYCLOUD_FALLBACK_HOST, DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL, Delegation, DelegationManager, DelegationRevocationReceipt, type DidCacheKeyOptions, type DidEqualsOptions, type DiscoverLocalTinyCloudNodeOptions, type DiscoveredLocalTinyCloudNode, ENCRYPTION_MANIFEST_SPACE, ENCRYPTION_PERMISSION_SERVICE, EXPIRY, type EnsData, EnsDataSchema, type EventEmitterStrategy, type ExpiryTier, type Extension, GenerateShareParams, ICapabilityKeyRegistry, type IENSResolver, type INotificationHandler, type ISessionManager, type ISessionStorage, ISharingService, type ISigner, type ISpace, type ISpaceCreationHandler, type ISpaceScopedDelegations, type ISpaceScopedSharing, type ISpaceService, type IUserAuthorization, type IWasmBindings, IdentityParseError, LOCAL_LINK_HOST_SUFFIX, LOCAL_LINK_PROBE_TIMEOUT_MS, LOCAL_LOOPBACK_PROBE_TIMEOUT_MS, type LocalNodeIdentityStore, type LocationCandidate, type LocationCandidateInput, type LocationRecord, type LocationRecordPayload, type LocationRecordSigner, LocationRecordValidationError, type LocationResolutionAttempt, type LocationSource, type Manifest, type ManifestDefaults, type ManifestKnowledge, type ManifestRegistryRecord, type ManifestSecretActions, ManifestValidationError, type NodeInfo, type OpenKeyCallbackStrategy, type OpenKeySigningRequestBody, type OpenKeySigningResponseBody, type OpenKeySigningStrategyOptions, type ParseRecapFromSiwe, type PartialSiweMessage, type PermissionEntry, PermissionNotInManifestError, type PersistedSessionData, type PersistedSessionProof, type PersistedTinyCloudSession, type PkhDidParts, ProtocolMismatchError, type ResolveCloudLocationOptions, type ResolveTinyCloudHostsOptions, type ResolvedCapabilities, type ResolvedCloudLocation, type ResolvedDelegate, type ResolvedTinyCloudHosts, type ResourceCapability, SECRETS_SPACE, SERVICE_LONG_TO_SHORT, SERVICE_SHORT_TO_LONG, type ServerHost, SessionExpiredError, ShareLink, type SignCallback, type SignInOptions, type SignRequest, type SignResponse, type SignStrategy, SilentNotificationHandler, type SiweConfig, SiweConfigSchema, Space, type SpaceAbilitiesMap, type SpaceConfig, type SpaceCreationContext, type SpaceDelegationParams, type SpaceErrorCode, SpaceErrorCodes, type SpaceHostResult, SpaceInfo, SpaceService, type SpaceServiceConfig, type SubsetCheckResult, TinyCloud, type TinyCloudConfig, type TinyCloudSession, UnsupportedFeatureError, type UserAuthorizationConfig, VAULT_PERMISSION_SERVICE, type ValidatedPersistedSessionProof, type ValidationError, VersionCheckError, type WasmRecapEntry, type WebStorageLike, actionContains, activateSessionWithHost, addressStorageKey, applyPrefix, buildSpaceUri, canonicalLocationPayload, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeRecapCaveats, checkNodeInfo, composeManifestRequest, createInMemoryLocalNodeIdentityStore, createLocalStorageLocalNodeIdentityStore, createOpenKeyCallbackSigningStrategy, createSpaceService, defaultSignStrategy, defaultSpaceCreationHandler, didCacheKey, didEquals, discoverLocalTinyCloudNode, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, fetchLocationRecord, fetchPeerId, httpUrlToMultiaddr, isCapabilitySubset, isEvmAddress, loadManifest, locationPayloadForRecord, makePkhSpaceId, makePublicSpaceId, manifestAbilitiesUnion, multiaddrToHttpUrl, normalizeDefaults, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseRecapCapabilities, parseSpaceUri, pkhDid, principalDid, principalDidEquals, recapCaveatsEqual, resolveCloudLocation, resolveManifest, resolveManifestKnowledgeRoot, resolveTinyCloudHosts, resourceCapabilitiesToAbilitiesMap, resourceCapabilitiesToSpaceAbilitiesMap, signLocationRecord, submitHostDelegation, validateClientSession, validateLocationRecord, validateLocationRecordPayload, validateManifest, validatePersistedSessionData, verifyDidKeyEd25519Signature, verifyLocationRecord };
|
|
3019
|
+
export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, type AbilitiesMap, type AccountApplication, type AccountApplicationListOptions, type AccountApplicationRegisterOptions, type AccountDelegation, type AccountDelegationListOptions, AccountDelegationPage, AccountDelegationQueryOptions, type AccountDelegationRevokeOptions, type AccountIndexEnsureResult, type AccountIndexRebuildResult, type AccountIndexStatus, type AccountIndexedReadOptions, AccountService, type AccountServiceConfig, type AccountSpace, type AccountSpaceListOptions, type AccountStatus, AutoApproveSpaceCreationHandler, type AutoRejectStrategy, type AutoSignStrategy, type Bytes, type CallbackStrategy, type CanonicalAddress, type CanonicalParsedNetworkId, CaveatedDelegationUnsupportedError, type ClientSession, ClientSessionSchema, CloudLocationResolutionError, type ComposeManifestOptions, type ComposedManifestRequest, type CreateDelegationFunction, CreateDelegationParams, DEFAULT_DEFAULTS, DEFAULT_EXPIRY, DEFAULT_KNOWLEDGE_ROOT, DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY, DEFAULT_LOCAL_NODE_URL, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DEFAULT_TINYCLOUD_FALLBACK_HOST, DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL, Delegation, DelegationManager, DelegationRevocationReceipt, type DidCacheKeyOptions, type DidEqualsOptions, type DiscoverLocalTinyCloudNodeOptions, type DiscoveredLocalTinyCloudNode, ENCRYPTION_MANIFEST_SPACE, ENCRYPTION_PERMISSION_SERVICE, EXPIRY, type EnsData, EnsDataSchema, type EventEmitterStrategy, type ExpiryTier, type Extension, GenerateShareParams, ICapabilityKeyRegistry, type IENSResolver, type INotificationHandler, type ISessionManager, type ISessionStorage, ISharingService, type ISigner, type ISpace, type ISpaceCreationHandler, type ISpaceScopedDelegations, type ISpaceScopedSharing, type ISpaceService, type IUserAuthorization, type IWasmBindings, IdentityParseError, LOCAL_LINK_HOST_SUFFIX, LOCAL_LINK_PROBE_TIMEOUT_MS, LOCAL_LOOPBACK_PROBE_TIMEOUT_MS, type LocalNodeIdentityStore, type LocationCandidate, type LocationCandidateInput, type LocationRecord, type LocationRecordPayload, type LocationRecordSigner, LocationRecordValidationError, type LocationResolutionAttempt, type LocationSource, type Manifest, type ManifestDefaults, type ManifestKnowledge, type ManifestRegistryRecord, type ManifestSecretActions, ManifestValidationError, type NodeInfo, type OpenKeyCallbackStrategy, type OpenKeySigningRequestBody, type OpenKeySigningResponseBody, type OpenKeySigningStrategyOptions, type ParseRecapFromSiwe, type PartialSiweMessage, type PermissionEntry, PermissionNotInManifestError, type PersistedSessionData, type PersistedSessionProof, type PersistedTinyCloudSession, type PkhDidParts, ProtocolMismatchError, type RegisterBatchSuccess, type ResolveCloudLocationOptions, type ResolveTinyCloudHostsOptions, type ResolvedCapabilities, type ResolvedCloudLocation, type ResolvedDelegate, type ResolvedTinyCloudHosts, type ResourceCapability, SECRETS_SPACE, SERVICE_LONG_TO_SHORT, SERVICE_SHORT_TO_LONG, type ServerHost, SessionExpiredError, ShareLink, type SignCallback, type SignInOptions, type SignRequest, type SignResponse, type SignStrategy, SilentNotificationHandler, type SiweConfig, SiweConfigSchema, Space, type SpaceAbilitiesMap, type SpaceConfig, type SpaceCreationContext, type SpaceDelegationParams, type SpaceErrorCode, SpaceErrorCodes, type SpaceHostResult, SpaceInfo, SpaceService, type SpaceServiceConfig, type SubsetCheckResult, TinyCloud, type TinyCloudConfig, type TinyCloudSession, UnsupportedFeatureError, type UserAuthorizationConfig, VAULT_PERMISSION_SERVICE, type ValidatedPersistedSessionProof, type ValidationError, VersionCheckError, type WasmRecapEntry, type WebStorageLike, actionContains, activateSessionWithHost, addressStorageKey, applyPrefix, buildSpaceUri, canonicalLocationPayload, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeRecapCaveats, checkNodeInfo, composeManifestRequest, createInMemoryLocalNodeIdentityStore, createLocalStorageLocalNodeIdentityStore, createOpenKeyCallbackSigningStrategy, createSpaceService, defaultSignStrategy, defaultSpaceCreationHandler, didCacheKey, didEquals, discoverLocalTinyCloudNode, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, fetchLocationRecord, fetchPeerId, httpUrlToMultiaddr, isCapabilitySubset, isEvmAddress, loadManifest, locationPayloadForRecord, makePkhSpaceId, makePublicSpaceId, manifestAbilitiesUnion, multiaddrToHttpUrl, normalizeDefaults, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseRecapCapabilities, parseSpaceUri, pkhDid, principalDid, principalDidEquals, recapCaveatsEqual, resolveCloudLocation, resolveManifest, resolveManifestKnowledgeRoot, resolveTinyCloudHosts, resourceCapabilitiesToAbilitiesMap, resourceCapabilitiesToSpaceAbilitiesMap, signLocationRecord, submitHostDelegation, validateClientSession, validateLocationRecord, validateLocationRecordPayload, validateManifest, validatePersistedSessionData, verifyDidKeyEd25519Signature, verifyLocationRecord };
|
package/dist/index.js
CHANGED
|
@@ -11793,7 +11793,8 @@ var TinyCloud = class _TinyCloud {
|
|
|
11793
11793
|
import {
|
|
11794
11794
|
err as err3,
|
|
11795
11795
|
ok as ok3,
|
|
11796
|
-
serviceError as serviceError3
|
|
11796
|
+
serviceError as serviceError3,
|
|
11797
|
+
ErrorCodes as ErrorCodes3
|
|
11797
11798
|
} from "@tinycloud/sdk-services";
|
|
11798
11799
|
import { ACCOUNT_INDEX_SCHEMA } from "@tinycloud/bootstrap";
|
|
11799
11800
|
var SERVICE_NAME2 = "account";
|
|
@@ -11945,6 +11946,60 @@ var AccountService = class {
|
|
|
11945
11946
|
await this.upsertSpaceIndexQuietly(registered);
|
|
11946
11947
|
return ok3(registered);
|
|
11947
11948
|
},
|
|
11949
|
+
/**
|
|
11950
|
+
* Register multiple spaces in one KV batch write + one multi-row index
|
|
11951
|
+
* write, instead of one `register()` round trip per space (TC-373).
|
|
11952
|
+
*
|
|
11953
|
+
* The stored records are computed exactly once and reused for both the
|
|
11954
|
+
* batch attempt and any reconciliation below, so a fallback never mints a
|
|
11955
|
+
* fresh timestamp for a space that already has a written record — a
|
|
11956
|
+
* second `spaceRecordFromInput` call would produce a new content hash and
|
|
11957
|
+
* leave the first attempt's blocks orphaned.
|
|
11958
|
+
*/
|
|
11959
|
+
registerBatch: async (spaces) => {
|
|
11960
|
+
if (spaces.length === 0) return ok3({ spaces: [] });
|
|
11961
|
+
await this.config.ensureAccountSpaceHosted?.();
|
|
11962
|
+
const kvResult = this.accountKV();
|
|
11963
|
+
if (!kvResult.ok) return kvResult;
|
|
11964
|
+
const stored = spaces.map((space) => spaceRecordFromInput(space));
|
|
11965
|
+
const registered = stored.map(
|
|
11966
|
+
(record) => spaceFromRecord(spaceKey(record.space_id), record)
|
|
11967
|
+
);
|
|
11968
|
+
const items = stored.map((record) => ({
|
|
11969
|
+
key: spaceKey(record.space_id),
|
|
11970
|
+
value: record
|
|
11971
|
+
}));
|
|
11972
|
+
const batchResult = await kvResult.data.batchPut(items);
|
|
11973
|
+
if (batchResult.ok) {
|
|
11974
|
+
await this.upsertSpacesIndexQuietly(registered);
|
|
11975
|
+
return ok3({ spaces: registered });
|
|
11976
|
+
}
|
|
11977
|
+
if (!isAmbiguousBatchFailure(batchResult.error)) {
|
|
11978
|
+
return accountErr(batchResult.error);
|
|
11979
|
+
}
|
|
11980
|
+
const reconcileFailures = [];
|
|
11981
|
+
for (const record of stored) {
|
|
11982
|
+
const written = await kvResult.data.put(spaceKey(record.space_id), record);
|
|
11983
|
+
if (!written.ok) {
|
|
11984
|
+
reconcileFailures.push(`${record.space_id}: ${written.error.message}`);
|
|
11985
|
+
}
|
|
11986
|
+
}
|
|
11987
|
+
if (reconcileFailures.length > 0) {
|
|
11988
|
+
return err3(
|
|
11989
|
+
serviceError3(
|
|
11990
|
+
"KV_BATCH_RECONCILE_FAILED",
|
|
11991
|
+
`KV batch write for ${items.length} space(s) failed ambiguously (${batchResult.error.message}) and per-space reconciliation also failed for: ${reconcileFailures.join("; ")}`,
|
|
11992
|
+
SERVICE_NAME2,
|
|
11993
|
+
{ cause: batchResult.error.cause, meta: { originalError: batchResult.error } }
|
|
11994
|
+
)
|
|
11995
|
+
);
|
|
11996
|
+
}
|
|
11997
|
+
console.warn(
|
|
11998
|
+
`[AccountService] KV batch write for ${items.length} space(s) returned an ambiguous error and was reconciled via per-space fallback. Original error: ${batchResult.error.message}`
|
|
11999
|
+
);
|
|
12000
|
+
await this.upsertSpacesIndexQuietly(registered);
|
|
12001
|
+
return ok3({ spaces: registered, recoveredFromBatchError: batchResult.error });
|
|
12002
|
+
},
|
|
11948
12003
|
syncAccessible: async () => {
|
|
11949
12004
|
const listed = await this.config.getSpaces().list();
|
|
11950
12005
|
if (!listed.ok) return accountErr(listed.error);
|
|
@@ -12331,6 +12386,47 @@ var AccountService = class {
|
|
|
12331
12386
|
if (!written.ok) return accountErr(written.error);
|
|
12332
12387
|
return ok3(void 0);
|
|
12333
12388
|
}
|
|
12389
|
+
async upsertSpacesIndexQuietly(spaces) {
|
|
12390
|
+
await ignoreIndexFailure(() => this.upsertSpacesIndex(spaces));
|
|
12391
|
+
}
|
|
12392
|
+
/**
|
|
12393
|
+
* Upsert multiple space index rows in ONE multi-row `INSERT OR REPLACE`
|
|
12394
|
+
* statement (TC-373), rather than one statement per space. This matters
|
|
12395
|
+
* because `IDatabaseHandle.batch()` executes its statement list as a plain
|
|
12396
|
+
* loop, not a single database transaction — an N-statement batch is not
|
|
12397
|
+
* atomic. A single multi-row INSERT is one SQLite statement, so it applies
|
|
12398
|
+
* atomically: all rows or none.
|
|
12399
|
+
*/
|
|
12400
|
+
async upsertSpacesIndex(spaces) {
|
|
12401
|
+
if (spaces.length === 0) return ok3(void 0);
|
|
12402
|
+
const dbResult = this.accountDb();
|
|
12403
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
12404
|
+
const schema = await this.ensureAccountIndex(dbResult.data);
|
|
12405
|
+
if (!schema.ok) return schema;
|
|
12406
|
+
const placeholders = spaces.map(() => "(?, ?, ?, ?, ?, ?, ?, ?, ?)").join(", ");
|
|
12407
|
+
const params = spaces.flatMap((space) => {
|
|
12408
|
+
const updatedAt = space.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
12409
|
+
return [
|
|
12410
|
+
space.spaceId,
|
|
12411
|
+
space.name,
|
|
12412
|
+
space.ownerDid,
|
|
12413
|
+
space.type,
|
|
12414
|
+
JSON.stringify(space.permissions),
|
|
12415
|
+
space.status,
|
|
12416
|
+
space.registeredAt ?? updatedAt,
|
|
12417
|
+
updatedAt,
|
|
12418
|
+
space.expiresAt?.toISOString() ?? null
|
|
12419
|
+
];
|
|
12420
|
+
});
|
|
12421
|
+
const written = await dbResult.data.batch([
|
|
12422
|
+
{
|
|
12423
|
+
sql: `INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES ${placeholders}`,
|
|
12424
|
+
params
|
|
12425
|
+
}
|
|
12426
|
+
]);
|
|
12427
|
+
if (!written.ok) return accountErr(written.error);
|
|
12428
|
+
return ok3(void 0);
|
|
12429
|
+
}
|
|
12334
12430
|
async deleteSpaceIndexQuietly(spaceId) {
|
|
12335
12431
|
await ignoreIndexFailure(() => this.deleteSpaceIndex(spaceId));
|
|
12336
12432
|
}
|
|
@@ -12657,6 +12753,17 @@ function accountErr(error) {
|
|
|
12657
12753
|
function isMissingIndexError(error) {
|
|
12658
12754
|
return /no such table:/i.test(error.message);
|
|
12659
12755
|
}
|
|
12756
|
+
var AMBIGUOUS_WRITE_STATUSES = /* @__PURE__ */ new Set([500, 502, 503, 504, 520, 522, 524]);
|
|
12757
|
+
function isAmbiguousBatchFailure(error) {
|
|
12758
|
+
if (error.code === ErrorCodes3.NETWORK_ERROR || error.code === ErrorCodes3.TIMEOUT) {
|
|
12759
|
+
return error.meta?.requestMayHaveDispatched === true;
|
|
12760
|
+
}
|
|
12761
|
+
if (error.code === ErrorCodes3.KV_WRITE_FAILED) {
|
|
12762
|
+
const status = error.meta?.status;
|
|
12763
|
+
return typeof status === "number" && AMBIGUOUS_WRITE_STATUSES.has(status);
|
|
12764
|
+
}
|
|
12765
|
+
return false;
|
|
12766
|
+
}
|
|
12660
12767
|
async function ignoreIndexFailure(task) {
|
|
12661
12768
|
try {
|
|
12662
12769
|
await task();
|
|
@@ -12672,7 +12779,7 @@ import {
|
|
|
12672
12779
|
ok as ok5,
|
|
12673
12780
|
err as err5,
|
|
12674
12781
|
serviceError as serviceError5,
|
|
12675
|
-
ErrorCodes as
|
|
12782
|
+
ErrorCodes as ErrorCodes4,
|
|
12676
12783
|
TinyCloudDebugLogger,
|
|
12677
12784
|
tinyCloudDebugLogger,
|
|
12678
12785
|
enableTinyCloudDebug,
|
|
@@ -15132,13 +15239,14 @@ async function discoverLocalTinyCloudNode(options2 = {}) {
|
|
|
15132
15239
|
}
|
|
15133
15240
|
const fetchFn = options2.fetch ?? globalThis.fetch;
|
|
15134
15241
|
const identityStore = options2.identityStore ?? defaultLocalNodeIdentityStore;
|
|
15135
|
-
const staticCandidates = [
|
|
15136
|
-
|
|
15242
|
+
const staticCandidates = [];
|
|
15243
|
+
if (options2.localNodeUrl) {
|
|
15244
|
+
staticCandidates.push({
|
|
15137
15245
|
source: "local-loopback",
|
|
15138
|
-
url: options2.localNodeUrl
|
|
15246
|
+
url: options2.localNodeUrl,
|
|
15139
15247
|
timeoutMs: LOCAL_LOOPBACK_PROBE_TIMEOUT_MS
|
|
15140
|
-
}
|
|
15141
|
-
|
|
15248
|
+
});
|
|
15249
|
+
}
|
|
15142
15250
|
if (options2.localLinkName) {
|
|
15143
15251
|
if (isValidDnsLabel(options2.localLinkName)) {
|
|
15144
15252
|
staticCandidates.push({
|
|
@@ -15591,7 +15699,7 @@ export {
|
|
|
15591
15699
|
EXPIRY,
|
|
15592
15700
|
EncryptionService,
|
|
15593
15701
|
EnsDataSchema,
|
|
15594
|
-
|
|
15702
|
+
ErrorCodes4 as ErrorCodes,
|
|
15595
15703
|
HOLDER_KEY_BINDING_PRESENTATION_SCHEMA,
|
|
15596
15704
|
HOOKS,
|
|
15597
15705
|
HooksService2 as HooksService,
|