@tinycloud/node-sdk 1.6.0 → 2.0.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/index.js CHANGED
@@ -17027,13 +17027,63 @@ var require_utils2 = __commonJS({
17027
17027
  }
17028
17028
  });
17029
17029
 
17030
- // src/index.ts
17031
- import { TinyCloud as TinyCloud2 } from "@tinycloud/sdk-core";
17030
+ // src/NodeWasmBindings.ts
17031
+ import {
17032
+ invoke,
17033
+ prepareSession,
17034
+ completeSessionSetup,
17035
+ ensureEip55,
17036
+ makeSpaceId,
17037
+ createDelegation,
17038
+ generateHostSIWEMessage,
17039
+ siweToDelegationHeaders,
17040
+ protocolVersion,
17041
+ TCWSessionManager,
17042
+ initPanicHook,
17043
+ vault_encrypt,
17044
+ vault_decrypt,
17045
+ vault_derive_key,
17046
+ vault_x25519_from_seed,
17047
+ vault_x25519_dh,
17048
+ vault_random_bytes,
17049
+ vault_sha256
17050
+ } from "@tinycloud/node-sdk-wasm";
17051
+ var _NodeWasmBindings = class _NodeWasmBindings {
17052
+ constructor() {
17053
+ this.invoke = invoke;
17054
+ this.prepareSession = prepareSession;
17055
+ this.completeSessionSetup = completeSessionSetup;
17056
+ this.ensureEip55 = ensureEip55;
17057
+ this.makeSpaceId = makeSpaceId;
17058
+ this.createDelegation = createDelegation;
17059
+ this.generateHostSIWEMessage = generateHostSIWEMessage;
17060
+ this.siweToDelegationHeaders = siweToDelegationHeaders;
17061
+ this.protocolVersion = protocolVersion;
17062
+ // Vault crypto
17063
+ this.vault_encrypt = vault_encrypt;
17064
+ this.vault_decrypt = vault_decrypt;
17065
+ this.vault_derive_key = vault_derive_key;
17066
+ this.vault_x25519_from_seed = vault_x25519_from_seed;
17067
+ this.vault_x25519_dh = vault_x25519_dh;
17068
+ this.vault_random_bytes = vault_random_bytes;
17069
+ this.vault_sha256 = vault_sha256;
17070
+ if (!_NodeWasmBindings.panicHookInitialized) {
17071
+ initPanicHook();
17072
+ _NodeWasmBindings.panicHookInitialized = true;
17073
+ }
17074
+ }
17075
+ createSessionManager() {
17076
+ return new TCWSessionManager();
17077
+ }
17078
+ // No ensureInitialized needed — Node WASM is synchronous
17079
+ };
17080
+ _NodeWasmBindings.panicHookInitialized = false;
17081
+ var NodeWasmBindings = _NodeWasmBindings;
17032
17082
 
17033
17083
  // src/signers/PrivateKeySigner.ts
17034
17084
  import {
17035
17085
  signEthereumMessage,
17036
- ensureEip55
17086
+ ensureEip55 as ensureEip552
17037
17087
  } from "@tinycloud/node-sdk-wasm";
17038
17088
  var PrivateKeySigner = class {
17039
17089
  /**
@@ -17072,7 +17122,7 @@ var PrivateKeySigner = class {
17072
17122
  const pubKeyWithoutPrefix = publicKey.slice(4);
17073
17123
  const hash3 = keccak2563("0x" + pubKeyWithoutPrefix);
17074
17124
  const address = "0x" + hash3.slice(-40);
17075
- return ensureEip55(address);
17125
+ return ensureEip552(address);
17076
17126
  } catch {
17077
17127
  return "0x" + this.privateKeyHex.slice(0, 40);
17078
17128
  }
@@ -17096,6 +17146,37 @@ var PrivateKeySigner = class {
17096
17146
  }
17097
17147
  };
17098
17148
 
17149
+ // src/TinyCloudNode.ts
17150
+ import {
17151
+ TinyCloud,
17152
+ activateSessionWithHost as activateSessionWithHost2,
17153
+ KVService as KVService2,
17154
+ SQLService as SQLService2,
17155
+ DuckDbService as DuckDbService2,
17156
+ DataVaultService,
17157
+ createVaultCrypto,
17158
+ ServiceContext as ServiceContext2,
17159
+ SilentNotificationHandler,
17160
+ DelegationManager,
17161
+ SpaceService,
17162
+ CapabilityKeyRegistry,
17163
+ SharingService,
17164
+ UnsupportedFeatureError,
17165
+ makePublicSpaceId
17166
+ } from "@tinycloud/sdk-core";
17167
+
17168
+ // src/authorization/NodeUserAuthorization.ts
17169
+ import {
17170
+ fetchPeerId,
17171
+ submitHostDelegation,
17172
+ activateSessionWithHost,
17173
+ checkNodeInfo,
17174
+ AutoApproveSpaceCreationHandler
17175
+ } from "@tinycloud/sdk-core";
17176
+
17177
+ // src/authorization/strategies.ts
17178
+ var defaultSignStrategy = { type: "auto-sign" };
17179
+
17099
17180
  // src/storage/MemorySessionStorage.ts
17100
17181
  var MemorySessionStorage = class {
17101
17182
  constructor() {
@@ -17167,157 +17248,12 @@ var MemorySessionStorage = class {
17167
17248
  }
17168
17249
  };
17169
17250
 
17170
- // src/storage/FileSessionStorage.ts
17171
- import { validatePersistedSessionData } from "@tinycloud/sdk-core";
17172
- import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "fs";
17173
- import { join } from "path";
17174
- var FileSessionStorage = class {
17175
- /**
17176
- * Create a new FileSessionStorage.
17177
- *
17178
- * @param baseDir - Directory to store session files (default: ~/.tinycloud/sessions)
17179
- */
17180
- constructor(baseDir) {
17181
- this.baseDir = baseDir || this.getDefaultDir();
17182
- this.ensureDirectoryExists();
17183
- }
17184
- /**
17185
- * Get the default session storage directory.
17186
- */
17187
- getDefaultDir() {
17188
- const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
17189
- return join(home, ".tinycloud", "sessions");
17190
- }
17191
- /**
17192
- * Ensure the storage directory exists.
17193
- */
17194
- ensureDirectoryExists() {
17195
- if (!existsSync(this.baseDir)) {
17196
- mkdirSync(this.baseDir, { recursive: true });
17197
- }
17198
- }
17199
- /**
17200
- * Get the file path for an address.
17201
- */
17202
- getFilePath(address) {
17203
- const normalizedAddress = address.toLowerCase();
17204
- const filename = `${normalizedAddress.replace("0x", "")}.json`;
17205
- return join(this.baseDir, filename);
17206
- }
17207
- /**
17208
- * Save a session for an address.
17209
- */
17210
- async save(address, session) {
17211
- const filePath = this.getFilePath(address);
17212
- const data = JSON.stringify(session, null, 2);
17213
- writeFileSync(filePath, data, "utf-8");
17214
- }
17215
- /**
17216
- * Load a session for an address.
17217
- */
17218
- async load(address) {
17219
- const filePath = this.getFilePath(address);
17220
- if (!existsSync(filePath)) {
17221
- return null;
17222
- }
17223
- try {
17224
- const data = readFileSync(filePath, "utf-8");
17225
- const parsed = JSON.parse(data);
17226
- const validation = validatePersistedSessionData(parsed);
17227
- if (!validation.ok) {
17228
- console.warn(`Invalid session data for ${address}:`, validation.error.message);
17229
- unlinkSync(filePath);
17230
- return null;
17231
- }
17232
- const session = validation.data;
17233
- const expiresAt = new Date(session.expiresAt);
17234
- if (expiresAt < /* @__PURE__ */ new Date()) {
17235
- unlinkSync(filePath);
17236
- return null;
17237
- }
17238
- return session;
17239
- } catch (error) {
17240
- try {
17241
- unlinkSync(filePath);
17242
- } catch {
17243
- }
17244
- return null;
17245
- }
17246
- }
17247
- /**
17248
- * Clear a session for an address.
17249
- */
17250
- async clear(address) {
17251
- const filePath = this.getFilePath(address);
17252
- if (existsSync(filePath)) {
17253
- unlinkSync(filePath);
17254
- }
17255
- }
17256
- /**
17257
- * Check if a session exists for an address.
17258
- */
17259
- exists(address) {
17260
- const filePath = this.getFilePath(address);
17261
- if (!existsSync(filePath)) {
17262
- return false;
17263
- }
17264
- try {
17265
- const data = readFileSync(filePath, "utf-8");
17266
- const session = JSON.parse(data);
17267
- const expiresAt = new Date(session.expiresAt);
17268
- if (expiresAt < /* @__PURE__ */ new Date()) {
17269
- unlinkSync(filePath);
17270
- return false;
17271
- }
17272
- return true;
17273
- } catch {
17274
- return false;
17275
- }
17276
- }
17277
- /**
17278
- * Check if file system storage is available.
17279
- */
17280
- isAvailable() {
17281
- try {
17282
- this.ensureDirectoryExists();
17283
- return existsSync(this.baseDir);
17284
- } catch {
17285
- return false;
17286
- }
17287
- }
17288
- };
17289
-
17290
- // src/authorization/NodeUserAuthorization.ts
17291
- import {
17292
- fetchPeerId,
17293
- submitHostDelegation,
17294
- activateSessionWithHost,
17295
- checkNodeVersion
17296
- } from "@tinycloud/sdk-core";
17297
- import {
17298
- TCWSessionManager as SessionManager,
17299
- prepareSession,
17300
- completeSessionSetup,
17301
- ensureEip55 as ensureEip552,
17302
- makeSpaceId,
17303
- initPanicHook,
17304
- generateHostSIWEMessage,
17305
- siweToDelegationHeaders,
17306
- protocolVersion
17307
- } from "@tinycloud/node-sdk-wasm";
17308
-
17309
- // src/authorization/strategies.ts
17310
- var defaultSignStrategy = { type: "auto-sign" };
17311
-
17312
17251
  // src/authorization/NodeUserAuthorization.ts
17313
- var _NodeUserAuthorization = class _NodeUserAuthorization {
17252
+ var NodeUserAuthorization = class {
17314
17253
  constructor(config) {
17315
17254
  this.extensions = [];
17316
17255
  this._nodeFeatures = [];
17317
- if (!_NodeUserAuthorization.wasmInitialized) {
17318
- initPanicHook();
17319
- _NodeUserAuthorization.wasmInitialized = true;
17320
- }
17256
+ this.wasm = config.wasmBindings;
17321
17257
  this.signer = config.signer;
17322
17258
  this.signStrategy = config.signStrategy ?? defaultSignStrategy;
17323
17259
  this.sessionStorage = config.sessionStorage ?? new MemorySessionStorage();
@@ -17360,9 +17296,10 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17360
17296
  };
17361
17297
  this.sessionExpirationMs = config.sessionExpirationMs ?? 60 * 60 * 1e3;
17362
17298
  this.autoCreateSpace = config.autoCreateSpace ?? false;
17299
+ this.spaceCreationHandler = config.spaceCreationHandler;
17363
17300
  this.tinycloudHosts = config.tinycloudHosts ?? ["https://node.tinycloud.xyz"];
17364
17301
  this.enablePublicSpace = config.enablePublicSpace ?? true;
17365
- this.sessionManager = new SessionManager();
17302
+ this.sessionManager = this.wasm.createSessionManager();
17366
17303
  }
17367
17304
  /**
17368
17305
  * The current active session (web-core compatible).
@@ -17403,7 +17340,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17403
17340
  const host = this.tinycloudHosts[0];
17404
17341
  const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
17405
17342
  const peerId = await fetchPeerId(host, spaceId);
17406
- const siwe = generateHostSIWEMessage({
17343
+ const siwe = this.wasm.generateHostSIWEMessage({
17407
17344
  address: this._address,
17408
17345
  chainId: this._chainId,
17409
17346
  domain: this.domain,
@@ -17412,7 +17349,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17412
17349
  peerId
17413
17350
  });
17414
17351
  const signature2 = await this.signMessage(siwe);
17415
- const headers = siweToDelegationHeaders({ siwe, signature: signature2 });
17352
+ const headers = this.wasm.siweToDelegationHeaders({ siwe, signature: signature2 });
17416
17353
  const result = await submitHostDelegation(host, headers);
17417
17354
  return result.success;
17418
17355
  }
@@ -17441,17 +17378,35 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17441
17378
  host,
17442
17379
  this._tinyCloudSession.delegationHeader
17443
17380
  );
17381
+ const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new AutoApproveSpaceCreationHandler() : void 0);
17382
+ const creationContext = {
17383
+ spaceId: primarySpaceId,
17384
+ address: this._address,
17385
+ chainId: this._chainId,
17386
+ host
17387
+ };
17444
17388
  if (result.success) {
17445
17389
  const primarySkipped = result.skipped?.includes(primarySpaceId);
17446
17390
  if (!primarySkipped) {
17447
17391
  return;
17448
17392
  }
17449
- if (!this.autoCreateSpace) {
17393
+ if (!handler) {
17450
17394
  return;
17451
17395
  }
17452
- const created = await this.hostSpace();
17453
- if (!created) {
17454
- throw new Error(`Failed to create space: ${primarySpaceId}`);
17396
+ const confirmed = await handler.confirmSpaceCreation(creationContext);
17397
+ if (!confirmed) {
17398
+ return;
17399
+ }
17400
+ try {
17401
+ const created = await this.hostSpace();
17402
+ if (!created) {
17403
+ const err = new Error(`Failed to create space: ${primarySpaceId}`);
17404
+ handler.onSpaceCreationFailed?.(creationContext, err);
17405
+ throw err;
17406
+ }
17407
+ } catch (error) {
17408
+ handler.onSpaceCreationFailed?.(creationContext, error instanceof Error ? error : new Error(String(error)));
17409
+ throw error;
17455
17410
  }
17456
17411
  await new Promise((resolve) => setTimeout(resolve, 100));
17457
17412
  const retryResult = await activateSessionWithHost(
@@ -17459,19 +17414,33 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17459
17414
  this._tinyCloudSession.delegationHeader
17460
17415
  );
17461
17416
  if (!retryResult.success) {
17462
- throw new Error(
17417
+ const err = new Error(
17463
17418
  `Failed to activate session after creating space: ${retryResult.error}`
17464
17419
  );
17420
+ handler.onSpaceCreationFailed?.(creationContext, err);
17421
+ throw err;
17465
17422
  }
17423
+ handler.onSpaceCreated?.(creationContext);
17466
17424
  return;
17467
17425
  }
17468
17426
  if (result.status === 404) {
17469
- if (!this.autoCreateSpace) {
17427
+ if (!handler) {
17470
17428
  return;
17471
17429
  }
17472
- const created = await this.hostSpace();
17473
- if (!created) {
17474
- throw new Error(`Failed to create space: ${primarySpaceId}`);
17430
+ const confirmed = await handler.confirmSpaceCreation(creationContext);
17431
+ if (!confirmed) {
17432
+ return;
17433
+ }
17434
+ try {
17435
+ const created = await this.hostSpace();
17436
+ if (!created) {
17437
+ const err = new Error(`Failed to create space: ${primarySpaceId}`);
17438
+ handler.onSpaceCreationFailed?.(creationContext, err);
17439
+ throw err;
17440
+ }
17441
+ } catch (error) {
17442
+ handler.onSpaceCreationFailed?.(creationContext, error instanceof Error ? error : new Error(String(error)));
17443
+ throw error;
17475
17444
  }
17476
17445
  await new Promise((resolve) => setTimeout(resolve, 100));
17477
17446
  const retryResult = await activateSessionWithHost(
@@ -17479,10 +17448,13 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17479
17448
  this._tinyCloudSession.delegationHeader
17480
17449
  );
17481
17450
  if (!retryResult.success) {
17482
- throw new Error(
17451
+ const err = new Error(
17483
17452
  `Failed to activate session after creating space: ${retryResult.error}`
17484
17453
  );
17454
+ handler.onSpaceCreationFailed?.(creationContext, err);
17455
+ throw err;
17485
17456
  }
17457
+ handler.onSpaceCreated?.(creationContext);
17486
17458
  return;
17487
17459
  }
17488
17460
  throw new Error(`Failed to activate session: ${result.error}`);
@@ -17499,7 +17471,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17499
17471
  async signIn() {
17500
17472
  this._address = await this.signer.getAddress();
17501
17473
  this._chainId = await this.signer.getChainId();
17502
- const address = ensureEip552(this._address);
17474
+ const address = this.wasm.ensureEip55(this._address);
17503
17475
  const chainId = this._chainId;
17504
17476
  const keyId = `session-${Date.now()}`;
17505
17477
  this.sessionManager.renameSessionKeyId("default", keyId);
@@ -17508,10 +17480,10 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17508
17480
  throw new Error("Failed to create session key");
17509
17481
  }
17510
17482
  const jwk = JSON.parse(jwkString);
17511
- const spaceId = makeSpaceId(address, chainId, this.spacePrefix);
17483
+ const spaceId = this.wasm.makeSpaceId(address, chainId, this.spacePrefix);
17512
17484
  const now = /* @__PURE__ */ new Date();
17513
17485
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
17514
- const prepared = prepareSession({
17486
+ const prepared = this.wasm.prepareSession({
17515
17487
  abilities: this.defaultActions,
17516
17488
  address,
17517
17489
  chainId,
@@ -17527,7 +17499,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17527
17499
  message: prepared.siwe,
17528
17500
  type: "siwe"
17529
17501
  });
17530
- const session = completeSessionSetup({
17502
+ const session = this.wasm.completeSessionSetup({
17531
17503
  ...prepared,
17532
17504
  signature: signature2
17533
17505
  });
@@ -17539,7 +17511,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17539
17511
  siwe: prepared.siwe,
17540
17512
  signature: signature2
17541
17513
  };
17542
- const spacesMetadata = this.enablePublicSpace ? { public: makeSpaceId(address, chainId, "public") } : void 0;
17514
+ const spacesMetadata = this.enablePublicSpace ? { public: this.wasm.makeSpaceId(address, chainId, "public") } : void 0;
17543
17515
  const tinyCloudSession = {
17544
17516
  address,
17545
17517
  chainId,
@@ -17575,7 +17547,8 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17575
17547
  this._tinyCloudSession = tinyCloudSession;
17576
17548
  this._address = address;
17577
17549
  this._chainId = chainId;
17578
- this._nodeFeatures = await checkNodeVersion(this.tinycloudHosts[0], protocolVersion());
17550
+ const nodeInfo = await checkNodeInfo(this.tinycloudHosts[0], this.wasm.protocolVersion());
17551
+ this._nodeFeatures = nodeInfo.features;
17579
17552
  for (const ext of this.extensions) {
17580
17553
  if (ext.afterSignIn) {
17581
17554
  await ext.afterSignIn(clientSession);
@@ -17637,7 +17610,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17637
17610
  * ```
17638
17611
  */
17639
17612
  async prepareSessionForSigning() {
17640
- const address = ensureEip552(await this.signer.getAddress());
17613
+ const address = this.wasm.ensureEip55(await this.signer.getAddress());
17641
17614
  const chainId = await this.signer.getChainId();
17642
17615
  const keyId = `session-${Date.now()}`;
17643
17616
  this.sessionManager.renameSessionKeyId("default", keyId);
@@ -17646,10 +17619,10 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17646
17619
  throw new Error("Failed to create session key");
17647
17620
  }
17648
17621
  const jwk = JSON.parse(jwkString);
17649
- const spaceId = makeSpaceId(address, chainId, this.spacePrefix);
17622
+ const spaceId = this.wasm.makeSpaceId(address, chainId, this.spacePrefix);
17650
17623
  const now = /* @__PURE__ */ new Date();
17651
17624
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
17652
- const prepared = prepareSession({
17625
+ const prepared = this.wasm.prepareSession({
17653
17626
  abilities: this.defaultActions,
17654
17627
  address,
17655
17628
  chainId,
@@ -17679,11 +17652,11 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17679
17652
  * @param jwk - The JWK from `prepareSessionForSigning()`
17680
17653
  */
17681
17654
  async signInWithPreparedSession(prepared, signature2, keyId, jwk) {
17682
- const session = completeSessionSetup({
17655
+ const session = this.wasm.completeSessionSetup({
17683
17656
  ...prepared,
17684
17657
  signature: signature2
17685
17658
  });
17686
- const address = ensureEip552(await this.signer.getAddress());
17659
+ const address = this.wasm.ensureEip55(await this.signer.getAddress());
17687
17660
  const chainId = await this.signer.getChainId();
17688
17661
  const clientSession = {
17689
17662
  address,
@@ -17693,7 +17666,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17693
17666
  siwe: prepared.siwe,
17694
17667
  signature: signature2
17695
17668
  };
17696
- const spacesMetadata = this.enablePublicSpace ? { public: makeSpaceId(address, chainId, "public") } : void 0;
17669
+ const spacesMetadata = this.enablePublicSpace ? { public: this.wasm.makeSpaceId(address, chainId, "public") } : void 0;
17697
17670
  const tinyCloudSession = {
17698
17671
  address,
17699
17672
  chainId,
@@ -17733,7 +17706,8 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17733
17706
  this._tinyCloudSession = tinyCloudSession;
17734
17707
  this._address = address;
17735
17708
  this._chainId = chainId;
17736
- this._nodeFeatures = await checkNodeVersion(this.tinycloudHosts[0], protocolVersion());
17709
+ const nodeInfo = await checkNodeInfo(this.tinycloudHosts[0], this.wasm.protocolVersion());
17710
+ this._nodeFeatures = nodeInfo.features;
17737
17711
  for (const ext of this.extensions) {
17738
17712
  if (ext.afterSignIn) {
17739
17713
  await ext.afterSignIn(clientSession);
@@ -17809,42 +17783,6 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17809
17783
  });
17810
17784
  }
17811
17785
  };
17812
- /** Flag to ensure WASM panic hook is only initialized once */
17813
- _NodeUserAuthorization.wasmInitialized = false;
17814
- var NodeUserAuthorization = _NodeUserAuthorization;
17815
-
17816
- // src/TinyCloudNode.ts
17817
- import {
17818
- TinyCloud,
17819
- activateSessionWithHost as activateSessionWithHost2,
17820
- KVService as KVService2,
17821
- SQLService as SQLService2,
17822
- DuckDbService as DuckDbService2,
17823
- DataVaultService,
17824
- createVaultCrypto,
17825
- ServiceContext as ServiceContext2,
17826
- DelegationManager,
17827
- SpaceService,
17828
- CapabilityKeyRegistry,
17829
- SharingService,
17830
- UnsupportedFeatureError
17831
- } from "@tinycloud/sdk-core";
17832
- import {
17833
- TCWSessionManager as SessionManager2,
17834
- prepareSession as prepareSession2,
17835
- completeSessionSetup as completeSessionSetup2,
17836
- ensureEip55 as ensureEip553,
17837
- invoke as invoke2,
17838
- initPanicHook as initPanicHook2,
17839
- createDelegation,
17840
- vault_encrypt,
17841
- vault_decrypt,
17842
- vault_derive_key,
17843
- vault_x25519_from_seed,
17844
- vault_x25519_dh,
17845
- vault_random_bytes,
17846
- vault_sha256
17847
- } from "@tinycloud/node-sdk-wasm";
17848
17786
 
17849
17787
  // src/DelegatedAccess.ts
17850
17788
  import {
@@ -17853,14 +17791,13 @@ import {
17853
17791
  DuckDbService,
17854
17792
  ServiceContext
17855
17793
  } from "@tinycloud/sdk-core";
17856
- import { invoke } from "@tinycloud/node-sdk-wasm";
17857
17794
  var DelegatedAccess = class {
17858
- constructor(session, delegation, host) {
17795
+ constructor(session, delegation, host, invoke2) {
17859
17796
  this.session = session;
17860
17797
  this._delegation = delegation;
17861
17798
  this.host = host;
17862
17799
  this._serviceContext = new ServiceContext({
17863
- invoke,
17800
+ invoke: invoke2,
17864
17801
  fetch: globalThis.fetch.bind(globalThis),
17865
17802
  hosts: [host]
17866
17803
  });
@@ -17978,7 +17915,7 @@ var WasmKeyProvider = class {
17978
17915
  * @returns Array of key IDs
17979
17916
  */
17980
17917
  listKeys() {
17981
- const keys = this.sessionManager.listSessionKeys();
17918
+ const keys = this.sessionManager.listSessionKeys?.();
17982
17919
  return Array.isArray(keys) ? keys : [];
17983
17920
  }
17984
17921
  /**
@@ -17998,7 +17935,7 @@ function createWasmKeyProvider(sessionManager) {
17998
17935
 
17999
17936
  // src/TinyCloudNode.ts
18000
17937
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
18001
- var _TinyCloudNode = class _TinyCloudNode {
17938
+ var TinyCloudNode = class _TinyCloudNode {
18002
17939
  /**
18003
17940
  * Create a new TinyCloudNode instance.
18004
17941
  *
@@ -18027,15 +17964,20 @@ var _TinyCloudNode = class _TinyCloudNode {
18027
17964
  this.auth = null;
18028
17965
  this.tc = null;
18029
17966
  this._chainId = 1;
18030
- if (!_TinyCloudNode.wasmInitialized) {
18031
- initPanicHook2();
18032
- _TinyCloudNode.wasmInitialized = true;
18033
- }
18034
17967
  this.config = {
18035
17968
  ...config,
18036
17969
  host: config.host ?? DEFAULT_HOST
18037
17970
  };
18038
- this.sessionManager = new SessionManager2();
17971
+ if (config.wasmBindings) {
17972
+ this.wasmBindings = config.wasmBindings;
17973
+ } else if (_TinyCloudNode.nodeDefaults) {
17974
+ this.wasmBindings = _TinyCloudNode.nodeDefaults.createWasmBindings();
17975
+ } else {
17976
+ throw new Error(
17977
+ "wasmBindings must be provided in config. Import from '@tinycloud/node-sdk' (not '/core') for automatic Node.js defaults."
17978
+ );
17979
+ }
17980
+ this.sessionManager = this.wasmBindings.createSessionManager();
18039
17981
  const defaultKeyId = "default";
18040
17982
  let jwkStr = this.sessionManager.jwk(defaultKeyId);
18041
17983
  if (jwkStr) {
@@ -18052,10 +17994,11 @@ var _TinyCloudNode = class _TinyCloudNode {
18052
17994
  this._keyProvider = new WasmKeyProvider({
18053
17995
  sessionManager: this.sessionManager
18054
17996
  });
17997
+ this.notificationHandler = config.notificationHandler ?? new SilentNotificationHandler();
18055
17998
  this._sharingService = new SharingService({
18056
17999
  hosts: [this.config.host],
18057
18000
  // session: undefined - not needed for receive()
18058
- invoke: invoke2,
18001
+ invoke: this.wasmBindings.invoke,
18059
18002
  fetch: globalThis.fetch.bind(globalThis),
18060
18003
  keyProvider: this._keyProvider,
18061
18004
  registry: this._capabilityRegistry,
@@ -18073,27 +18016,48 @@ var _TinyCloudNode = class _TinyCloudNode {
18073
18016
  return kvService;
18074
18017
  }
18075
18018
  });
18076
- if (config.privateKey) {
18077
- this.signer = new PrivateKeySigner(config.privateKey, this._chainId);
18078
- const host = this.config.host;
18079
- const domain = config.domain ?? new URL(host).hostname;
18080
- this.auth = new NodeUserAuthorization({
18081
- signer: this.signer,
18082
- signStrategy: { type: "auto-sign" },
18083
- sessionStorage: config.sessionStorage ?? new MemorySessionStorage(),
18084
- domain,
18085
- spacePrefix: config.prefix,
18086
- sessionExpirationMs: config.sessionExpirationMs ?? 60 * 60 * 1e3,
18087
- tinycloudHosts: [host],
18088
- autoCreateSpace: config.autoCreateSpace,
18089
- enablePublicSpace: config.enablePublicSpace ?? true
18090
- });
18091
- this.tc = new TinyCloud(this.auth);
18019
+ if (config.signer) {
18020
+ this.signer = config.signer;
18021
+ this.setupAuth(config);
18022
+ } else if (config.privateKey) {
18023
+ if (!_TinyCloudNode.nodeDefaults) {
18024
+ throw new Error(
18025
+ "privateKey requires PrivateKeySigner. Either provide a signer in config, or import from '@tinycloud/node-sdk' (not '/core') for automatic Node.js defaults."
18026
+ );
18027
+ }
18028
+ this.signer = _TinyCloudNode.nodeDefaults.createSigner(config.privateKey, this._chainId);
18029
+ this.setupAuth(config);
18092
18030
  }
18093
18031
  }
18032
+ /** @internal Register Node.js-specific defaults (NodeWasmBindings, PrivateKeySigner) */
18033
+ static registerNodeDefaults(defaults) {
18034
+ _TinyCloudNode.nodeDefaults = defaults;
18035
+ }
18094
18036
  get nodeFeatures() {
18095
18037
  return this.auth?.nodeFeatures ?? [];
18096
18038
  }
18039
+ /**
18040
+ * Set up authorization handler and TinyCloud instance.
18041
+ * @internal
18042
+ */
18043
+ setupAuth(config) {
18044
+ const host = this.config.host;
18045
+ const domain = config.domain ?? new URL(host).hostname;
18046
+ this.auth = new NodeUserAuthorization({
18047
+ signer: this.signer,
18048
+ signStrategy: { type: "auto-sign" },
18049
+ wasmBindings: this.wasmBindings,
18050
+ sessionStorage: config.sessionStorage ?? new MemorySessionStorage(),
18051
+ domain,
18052
+ spacePrefix: config.prefix,
18053
+ sessionExpirationMs: config.sessionExpirationMs ?? 60 * 60 * 1e3,
18054
+ tinycloudHosts: [host],
18055
+ autoCreateSpace: config.autoCreateSpace,
18056
+ enablePublicSpace: config.enablePublicSpace ?? true,
18057
+ spaceCreationHandler: config.spaceCreationHandler
18058
+ });
18059
+ this.tc = new TinyCloud(this.auth);
18060
+ }
18097
18061
  /**
18098
18062
  * Get the primary identity DID for this user.
18099
18063
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -18155,6 +18119,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18155
18119
  "Cannot signIn() in session-only mode. Provide a privateKey in config to create your own space."
18156
18120
  );
18157
18121
  }
18122
+ await this.wasmBindings.ensureInitialized?.();
18158
18123
  this._address = await this.signer.getAddress();
18159
18124
  this._chainId = await this.signer.getChainId();
18160
18125
  this._kv = void 0;
@@ -18163,6 +18128,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18163
18128
  this._serviceContext = void 0;
18164
18129
  await this.tc.signIn();
18165
18130
  this.initializeServices();
18131
+ this.notificationHandler.success("Successfully signed in");
18166
18132
  }
18167
18133
  /**
18168
18134
  * Restore a previously established session from stored delegation data.
@@ -18174,6 +18140,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18174
18140
  * @param sessionData - The stored delegation data from the browser flow
18175
18141
  */
18176
18142
  async restoreSession(sessionData) {
18143
+ await this.wasmBindings.ensureInitialized?.();
18177
18144
  this._kv = void 0;
18178
18145
  this._sql = void 0;
18179
18146
  this._duckdb = void 0;
@@ -18185,7 +18152,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18185
18152
  this._chainId = sessionData.chainId;
18186
18153
  }
18187
18154
  this._serviceContext = new ServiceContext2({
18188
- invoke: invoke2,
18155
+ invoke: this.wasmBindings.invoke,
18189
18156
  fetch: globalThis.fetch.bind(globalThis),
18190
18157
  hosts: [this.config.host]
18191
18158
  });
@@ -18206,6 +18173,43 @@ var _TinyCloudNode = class _TinyCloudNode {
18206
18173
  jwk: sessionData.jwk
18207
18174
  };
18208
18175
  this._serviceContext.setSession(serviceSession);
18176
+ const wasm = this.wasmBindings;
18177
+ const vaultCrypto = createVaultCrypto({
18178
+ vault_encrypt: wasm.vault_encrypt,
18179
+ vault_decrypt: wasm.vault_decrypt,
18180
+ vault_derive_key: wasm.vault_derive_key,
18181
+ vault_x25519_from_seed: wasm.vault_x25519_from_seed,
18182
+ vault_x25519_dh: wasm.vault_x25519_dh,
18183
+ vault_random_bytes: wasm.vault_random_bytes,
18184
+ vault_sha256: wasm.vault_sha256
18185
+ });
18186
+ const self2 = this;
18187
+ this._vault = new DataVaultService({
18188
+ spaceId: sessionData.spaceId,
18189
+ crypto: vaultCrypto,
18190
+ tc: {
18191
+ kv: this._kv,
18192
+ ensurePublicSpace: async () => {
18193
+ try {
18194
+ await self2.ensurePublicSpace();
18195
+ return { ok: true, data: void 0 };
18196
+ } catch (error) {
18197
+ return { ok: false, error: { code: "STORAGE_ERROR", message: error instanceof Error ? error.message : String(error), service: "vault" } };
18198
+ }
18199
+ },
18200
+ get publicKV() {
18201
+ return self2._publicKV ?? self2.tc.publicKV;
18202
+ },
18203
+ readPublicSpace: (host, spaceId, key2) => TinyCloud.readPublicSpace(host, spaceId, key2),
18204
+ makePublicSpaceId: TinyCloud.makePublicSpaceId,
18205
+ did: this.did,
18206
+ address: sessionData.address ?? this._address ?? "",
18207
+ chainId: sessionData.chainId ?? this._chainId,
18208
+ hosts: [this.config.host]
18209
+ }
18210
+ });
18211
+ this._vault.initialize(this._serviceContext);
18212
+ this._serviceContext.registerService("vault", this._vault);
18209
18213
  this.initializeV2Services(serviceSession);
18210
18214
  }
18211
18215
  /**
@@ -18240,17 +18244,61 @@ var _TinyCloudNode = class _TinyCloudNode {
18240
18244
  const prefix = options?.prefix ?? "default";
18241
18245
  const host = this.config.host;
18242
18246
  const domain = new URL(host).hostname;
18243
- this.signer = new PrivateKeySigner(privateKey);
18247
+ if (!_TinyCloudNode.nodeDefaults) {
18248
+ throw new Error(
18249
+ "connectWallet() requires PrivateKeySigner. Use connectSigner() instead, or import from '@tinycloud/node-sdk' (not '/core') for automatic Node.js defaults."
18250
+ );
18251
+ }
18252
+ this.signer = _TinyCloudNode.nodeDefaults.createSigner(privateKey);
18253
+ this.auth = new NodeUserAuthorization({
18254
+ signer: this.signer,
18255
+ signStrategy: { type: "auto-sign" },
18256
+ wasmBindings: this.wasmBindings,
18257
+ sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
18258
+ domain,
18259
+ spacePrefix: prefix,
18260
+ sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
18261
+ tinycloudHosts: [host],
18262
+ autoCreateSpace: this.config.autoCreateSpace,
18263
+ enablePublicSpace: this.config.enablePublicSpace ?? true,
18264
+ spaceCreationHandler: this.config.spaceCreationHandler
18265
+ });
18266
+ this.tc = new TinyCloud(this.auth);
18267
+ this.config.prefix = prefix;
18268
+ }
18269
+ /**
18270
+ * Connect any ISigner to upgrade from session-only mode to wallet mode.
18271
+ *
18272
+ * Same as connectWallet() but accepts any ISigner implementation instead
18273
+ * of a raw private key string. Use this for browser wallets, hardware wallets,
18274
+ * or custom signing backends.
18275
+ *
18276
+ * Note: This does NOT automatically sign in. Call signIn() after connecting.
18277
+ *
18278
+ * @param signer - Any ISigner implementation
18279
+ * @param options - Optional configuration
18280
+ * @param options.prefix - Space name prefix (defaults to "default")
18281
+ */
18282
+ connectSigner(signer, options) {
18283
+ if (this.signer) {
18284
+ throw new Error("Signer already connected. Cannot connect another signer.");
18285
+ }
18286
+ const prefix = options?.prefix ?? "default";
18287
+ const host = this.config.host;
18288
+ const domain = new URL(host).hostname;
18289
+ this.signer = signer;
18244
18290
  this.auth = new NodeUserAuthorization({
18245
18291
  signer: this.signer,
18246
18292
  signStrategy: { type: "auto-sign" },
18293
+ wasmBindings: this.wasmBindings,
18247
18294
  sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
18248
18295
  domain,
18249
18296
  spacePrefix: prefix,
18250
18297
  sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
18251
18298
  tinycloudHosts: [host],
18252
18299
  autoCreateSpace: this.config.autoCreateSpace,
18253
- enablePublicSpace: this.config.enablePublicSpace ?? true
18300
+ enablePublicSpace: this.config.enablePublicSpace ?? true,
18301
+ spaceCreationHandler: this.config.spaceCreationHandler
18254
18302
  });
18255
18303
  this.tc = new TinyCloud(this.auth);
18256
18304
  this.config.prefix = prefix;
@@ -18264,9 +18312,9 @@ var _TinyCloudNode = class _TinyCloudNode {
18264
18312
  if (!session) {
18265
18313
  return;
18266
18314
  }
18267
- this.tc.initializeServices(invoke2, [this.config.host]);
18315
+ this.tc.initializeServices(this.wasmBindings.invoke, [this.config.host]);
18268
18316
  this._serviceContext = new ServiceContext2({
18269
- invoke: invoke2,
18317
+ invoke: this.wasmBindings.invoke,
18270
18318
  fetch: globalThis.fetch.bind(globalThis),
18271
18319
  hosts: [this.config.host]
18272
18320
  });
@@ -18293,14 +18341,15 @@ var _TinyCloudNode = class _TinyCloudNode {
18293
18341
  };
18294
18342
  this._serviceContext.setSession(serviceSession);
18295
18343
  this.tc.serviceContext.setSession(serviceSession);
18344
+ const wasm = this.wasmBindings;
18296
18345
  const vaultCrypto = createVaultCrypto({
18297
- vault_encrypt,
18298
- vault_decrypt,
18299
- vault_derive_key,
18300
- vault_x25519_from_seed,
18301
- vault_x25519_dh,
18302
- vault_random_bytes,
18303
- vault_sha256
18346
+ vault_encrypt: wasm.vault_encrypt,
18347
+ vault_decrypt: wasm.vault_decrypt,
18348
+ vault_derive_key: wasm.vault_derive_key,
18349
+ vault_x25519_from_seed: wasm.vault_x25519_from_seed,
18350
+ vault_x25519_dh: wasm.vault_x25519_dh,
18351
+ vault_random_bytes: wasm.vault_random_bytes,
18352
+ vault_sha256: wasm.vault_sha256
18304
18353
  });
18305
18354
  const self2 = this;
18306
18355
  this._vault = new DataVaultService({
@@ -18413,13 +18462,13 @@ var _TinyCloudNode = class _TinyCloudNode {
18413
18462
  this._delegationManager = new DelegationManager({
18414
18463
  hosts: [this.config.host],
18415
18464
  session: serviceSession,
18416
- invoke: invoke2,
18465
+ invoke: this.wasmBindings.invoke,
18417
18466
  fetch: globalThis.fetch.bind(globalThis)
18418
18467
  });
18419
18468
  this._spaceService = new SpaceService({
18420
18469
  hosts: [this.config.host],
18421
18470
  session: serviceSession,
18422
- invoke: invoke2,
18471
+ invoke: this.wasmBindings.invoke,
18423
18472
  fetch: globalThis.fetch.bind(globalThis),
18424
18473
  capabilityRegistry: this._capabilityRegistry,
18425
18474
  userDid: this.did,
@@ -18480,7 +18529,10 @@ var _TinyCloudNode = class _TinyCloudNode {
18480
18529
  delegationManager: this._delegationManager,
18481
18530
  sessionExpiry: this.getSessionExpiry(),
18482
18531
  // WASM-based delegation creation (preferred - no server roundtrip)
18483
- createDelegationWasm: (params) => this.createDelegationWrapper(params)
18532
+ createDelegationWasm: (params) => this.createDelegationWrapper(params),
18533
+ // Root delegation for long-lived share links (bypasses session expiry)
18534
+ // In node-sdk we have direct signer access, so no popup needed
18535
+ onRootDelegationNeeded: this.signer ? async (params) => this.createRootDelegationForSharing(params) : void 0
18484
18536
  });
18485
18537
  this._spaceService.updateConfig({
18486
18538
  sharingService: this._sharingService
@@ -18507,7 +18559,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18507
18559
  spaceId: params.session.spaceId,
18508
18560
  verificationMethod: params.session.verificationMethod
18509
18561
  };
18510
- const result = createDelegation(
18562
+ const result = this.wasmBindings.createDelegation(
18511
18563
  wasmSession,
18512
18564
  params.delegateDID,
18513
18565
  params.spaceId,
@@ -18525,6 +18577,67 @@ var _TinyCloudNode = class _TinyCloudNode {
18525
18577
  expiry: new Date(result.expiry * 1e3)
18526
18578
  };
18527
18579
  }
18580
+ /**
18581
+ * Create a direct root delegation from the wallet to a share key.
18582
+ * This bypasses the session delegation chain, allowing share links
18583
+ * with expiry longer than the current session.
18584
+ * @internal
18585
+ */
18586
+ async createRootDelegationForSharing(params) {
18587
+ if (!this.signer) {
18588
+ return void 0;
18589
+ }
18590
+ const session = this.auth?.tinyCloudSession;
18591
+ if (!session) {
18592
+ return void 0;
18593
+ }
18594
+ try {
18595
+ const host = this.config.host;
18596
+ const now = /* @__PURE__ */ new Date();
18597
+ const abilities = {
18598
+ kv: {
18599
+ [params.path]: params.actions
18600
+ }
18601
+ };
18602
+ const prepared = this.wasmBindings.prepareSession({
18603
+ abilities,
18604
+ address: this.wasmBindings.ensureEip55(session.address),
18605
+ chainId: session.chainId,
18606
+ domain: new URL(host).hostname,
18607
+ issuedAt: now.toISOString(),
18608
+ expirationTime: params.requestedExpiry.toISOString(),
18609
+ spaceId: params.spaceId,
18610
+ delegateUri: params.shareKeyDID
18611
+ });
18612
+ const signature2 = await this.signer.signMessage(prepared.siwe);
18613
+ const delegationSession = this.wasmBindings.completeSessionSetup({
18614
+ ...prepared,
18615
+ signature: signature2
18616
+ });
18617
+ const activateResult = await activateSessionWithHost2(
18618
+ host,
18619
+ delegationSession.delegationHeader
18620
+ );
18621
+ if (!activateResult.success) {
18622
+ return void 0;
18623
+ }
18624
+ return {
18625
+ cid: delegationSession.delegationCid,
18626
+ delegateDID: params.shareKeyDID,
18627
+ delegatorDID: `did:pkh:eip155:${session.chainId}:${session.address}`,
18628
+ spaceId: params.spaceId,
18629
+ path: params.path,
18630
+ actions: params.actions,
18631
+ expiry: params.requestedExpiry,
18632
+ isRevoked: false,
18633
+ allowSubDelegation: true,
18634
+ createdAt: now,
18635
+ authHeader: delegationSession.delegationHeader.Authorization
18636
+ };
18637
+ } catch {
18638
+ return void 0;
18639
+ }
18640
+ }
18528
18641
  /**
18529
18642
  * Track a received delegation in the capability registry.
18530
18643
  * @internal
@@ -18795,9 +18908,9 @@ var _TinyCloudNode = class _TinyCloudNode {
18795
18908
  const now = /* @__PURE__ */ new Date();
18796
18909
  const expiryMs = 60 * 60 * 1e3;
18797
18910
  const expirationTime = new Date(now.getTime() + expiryMs);
18798
- const prepared = prepareSession2({
18911
+ const prepared = this.wasmBindings.prepareSession({
18799
18912
  abilities,
18800
- address: ensureEip553(this.session.address),
18913
+ address: this.wasmBindings.ensureEip55(this.session.address),
18801
18914
  chainId: this.session.chainId,
18802
18915
  domain: new URL(this.config.host).hostname,
18803
18916
  issuedAt: now.toISOString(),
@@ -18807,7 +18920,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18807
18920
  parents: [this.session.delegationCid]
18808
18921
  });
18809
18922
  const signature2 = await this.signer.signMessage(prepared.siwe);
18810
- const delegationSession = completeSessionSetup2({
18923
+ const delegationSession = this.wasmBindings.completeSessionSetup({
18811
18924
  ...prepared,
18812
18925
  signature: signature2
18813
18926
  });
@@ -18840,7 +18953,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18840
18953
  if (this._serviceContext) {
18841
18954
  const publicKV = new KVService2({ prefix: "" });
18842
18955
  const publicContext = new ServiceContext2({
18843
- invoke: invoke2,
18956
+ invoke: this.wasmBindings.invoke,
18844
18957
  fetch: this._serviceContext.fetch,
18845
18958
  hosts: this._serviceContext.hosts
18846
18959
  });
@@ -18941,6 +19054,11 @@ var _TinyCloudNode = class _TinyCloudNode {
18941
19054
  if (!session) {
18942
19055
  throw new Error("Not signed in. Call signIn() first.");
18943
19056
  }
19057
+ if (params.delegateDID.endsWith(".eth") && this.config.ensResolver) {
19058
+ const address = await this.config.ensResolver.resolveAddress(params.delegateDID);
19059
+ if (!address) throw new Error(`Could not resolve ENS name: ${params.delegateDID}`);
19060
+ params = { ...params, delegateDID: `did:pkh:eip155:1:${address}` };
19061
+ }
18944
19062
  const abilities = {};
18945
19063
  const kvActions = params.actions.filter((a) => a.startsWith("tinycloud.kv/"));
18946
19064
  const sqlActions = params.actions.filter((a) => a.startsWith("tinycloud.sql/"));
@@ -18957,9 +19075,9 @@ var _TinyCloudNode = class _TinyCloudNode {
18957
19075
  const now = /* @__PURE__ */ new Date();
18958
19076
  const expiryMs = params.expiryMs ?? 60 * 60 * 1e3;
18959
19077
  const expirationTime = new Date(now.getTime() + expiryMs);
18960
- const prepared = prepareSession2({
19078
+ const prepared = this.wasmBindings.prepareSession({
18961
19079
  abilities,
18962
- address: ensureEip553(session.address),
19080
+ address: this.wasmBindings.ensureEip55(session.address),
18963
19081
  chainId: session.chainId,
18964
19082
  domain: new URL(this.config.host).hostname,
18965
19083
  issuedAt: now.toISOString(),
@@ -18969,7 +19087,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18969
19087
  parents: [session.delegationCid]
18970
19088
  });
18971
19089
  const signature2 = await this.signer.signMessage(prepared.siwe);
18972
- const delegationSession = completeSessionSetup2({
19090
+ const delegationSession = this.wasmBindings.completeSessionSetup({
18973
19091
  ...prepared,
18974
19092
  signature: signature2
18975
19093
  });
@@ -18980,7 +19098,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18980
19098
  if (!activateResult.success) {
18981
19099
  throw new Error(`Failed to activate delegation: ${activateResult.error}`);
18982
19100
  }
18983
- return {
19101
+ const result = {
18984
19102
  cid: delegationSession.delegationCid,
18985
19103
  delegationHeader: delegationSession.delegationHeader,
18986
19104
  spaceId: params.spaceIdOverride ?? session.spaceId,
@@ -18993,6 +19111,52 @@ var _TinyCloudNode = class _TinyCloudNode {
18993
19111
  chainId: session.chainId,
18994
19112
  host: this.config.host
18995
19113
  };
19114
+ const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
19115
+ if (hasKvActions && params.includePublicSpace !== false) {
19116
+ const publicSpaceId = makePublicSpaceId(
19117
+ this.wasmBindings.ensureEip55(session.address),
19118
+ session.chainId
19119
+ );
19120
+ const publicAbilities = {
19121
+ kv: { "": ["tinycloud.kv/get", "tinycloud.kv/put", "tinycloud.kv/metadata"] }
19122
+ };
19123
+ const publicPrepared = this.wasmBindings.prepareSession({
19124
+ abilities: publicAbilities,
19125
+ address: this.wasmBindings.ensureEip55(session.address),
19126
+ chainId: session.chainId,
19127
+ domain: new URL(this.config.host).hostname,
19128
+ issuedAt: now.toISOString(),
19129
+ expirationTime: expirationTime.toISOString(),
19130
+ spaceId: publicSpaceId,
19131
+ delegateUri: params.delegateDID,
19132
+ parents: [session.delegationCid]
19133
+ });
19134
+ const publicSignature = await this.signer.signMessage(publicPrepared.siwe);
19135
+ const publicSession = this.wasmBindings.completeSessionSetup({
19136
+ ...publicPrepared,
19137
+ signature: publicSignature
19138
+ });
19139
+ const publicActivateResult = await activateSessionWithHost2(
19140
+ this.config.host,
19141
+ publicSession.delegationHeader
19142
+ );
19143
+ if (publicActivateResult.success) {
19144
+ result.publicDelegation = {
19145
+ cid: publicSession.delegationCid,
19146
+ delegationHeader: publicSession.delegationHeader,
19147
+ spaceId: publicSpaceId,
19148
+ path: "",
19149
+ actions: ["tinycloud.kv/get", "tinycloud.kv/put", "tinycloud.kv/metadata"],
19150
+ disableSubDelegation: params.disableSubDelegation ?? false,
19151
+ expiry: expirationTime,
19152
+ delegateDID: params.delegateDID,
19153
+ ownerAddress: session.address,
19154
+ chainId: session.chainId,
19155
+ host: this.config.host
19156
+ };
19157
+ }
19158
+ }
19159
+ return result;
18996
19160
  }
18997
19161
  /**
18998
19162
  * Use a delegation received from another user.
@@ -19032,7 +19196,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19032
19196
  // Not used in session-only mode
19033
19197
  };
19034
19198
  this.trackReceivedDelegation(delegation, this.sessionKeyJwk);
19035
- return new DelegatedAccess(session2, delegation, targetHost);
19199
+ return new DelegatedAccess(session2, delegation, targetHost, this.wasmBindings.invoke);
19036
19200
  }
19037
19201
  const mySession = this.auth?.tinyCloudSession;
19038
19202
  if (!mySession) {
@@ -19055,9 +19219,9 @@ var _TinyCloudNode = class _TinyCloudNode {
19055
19219
  const now = /* @__PURE__ */ new Date();
19056
19220
  const maxExpiry = new Date(now.getTime() + 60 * 60 * 1e3);
19057
19221
  const expirationTime = delegation.expiry < maxExpiry ? delegation.expiry : maxExpiry;
19058
- const prepared = prepareSession2({
19222
+ const prepared = this.wasmBindings.prepareSession({
19059
19223
  abilities,
19060
- address: ensureEip553(mySession.address),
19224
+ address: this.wasmBindings.ensureEip55(mySession.address),
19061
19225
  chainId: mySession.chainId,
19062
19226
  domain: new URL(targetHost).hostname,
19063
19227
  issuedAt: now.toISOString(),
@@ -19067,7 +19231,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19067
19231
  parents: [delegation.cid]
19068
19232
  });
19069
19233
  const signature2 = await this.signer.signMessage(prepared.siwe);
19070
- const invokerSession = completeSessionSetup2({
19234
+ const invokerSession = this.wasmBindings.completeSessionSetup({
19071
19235
  ...prepared,
19072
19236
  signature: signature2
19073
19237
  });
@@ -19091,7 +19255,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19091
19255
  signature: signature2
19092
19256
  };
19093
19257
  this.trackReceivedDelegation(delegation, jwk);
19094
- return new DelegatedAccess(session, delegation, targetHost);
19258
+ return new DelegatedAccess(session, delegation, targetHost, this.wasmBindings.invoke);
19095
19259
  }
19096
19260
  /**
19097
19261
  * Create a sub-delegation from a received delegation.
@@ -19144,9 +19308,9 @@ var _TinyCloudNode = class _TinyCloudNode {
19144
19308
  abilities.duckdb = { [params.path]: duckdbActions };
19145
19309
  }
19146
19310
  const targetHost = parentDelegation.host ?? this.config.host;
19147
- const prepared = prepareSession2({
19311
+ const prepared = this.wasmBindings.prepareSession({
19148
19312
  abilities,
19149
- address: ensureEip553(this._address),
19313
+ address: this.wasmBindings.ensureEip55(this._address),
19150
19314
  chainId: this._chainId,
19151
19315
  domain: new URL(targetHost).hostname,
19152
19316
  issuedAt: now.toISOString(),
@@ -19156,7 +19320,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19156
19320
  parents: [parentDelegation.cid]
19157
19321
  });
19158
19322
  const signature2 = await this.signer.signMessage(prepared.siwe);
19159
- const subDelegationSession = completeSessionSetup2({
19323
+ const subDelegationSession = this.wasmBindings.completeSessionSetup({
19160
19324
  ...prepared,
19161
19325
  signature: signature2
19162
19326
  });
@@ -19182,9 +19346,140 @@ var _TinyCloudNode = class _TinyCloudNode {
19182
19346
  };
19183
19347
  }
19184
19348
  };
19185
- /** Flag to ensure WASM panic hook is only initialized once */
19186
- _TinyCloudNode.wasmInitialized = false;
19187
- var TinyCloudNode = _TinyCloudNode;
19349
+
19350
+ // src/nodeDefaults.ts
19351
+ TinyCloudNode.registerNodeDefaults({
19352
+ createWasmBindings: () => new NodeWasmBindings(),
19353
+ createSigner: (privateKey, chainId) => new PrivateKeySigner(privateKey, chainId)
19354
+ });
19355
+
19356
+ // src/index.ts
19357
+ import { TinyCloud as TinyCloud2 } from "@tinycloud/sdk-core";
19358
+ import {
19359
+ SilentNotificationHandler as SilentNotificationHandler2,
19360
+ AutoApproveSpaceCreationHandler as AutoApproveSpaceCreationHandler2,
19361
+ defaultSpaceCreationHandler
19362
+ } from "@tinycloud/sdk-core";
19363
+
19364
+ // src/storage/FileSessionStorage.ts
19365
+ import { validatePersistedSessionData } from "@tinycloud/sdk-core";
19366
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "fs";
19367
+ import { join } from "path";
19368
+ var FileSessionStorage = class {
19369
+ /**
19370
+ * Create a new FileSessionStorage.
19371
+ *
19372
+ * @param baseDir - Directory to store session files (default: ~/.tinycloud/sessions)
19373
+ */
19374
+ constructor(baseDir) {
19375
+ this.baseDir = baseDir || this.getDefaultDir();
19376
+ this.ensureDirectoryExists();
19377
+ }
19378
+ /**
19379
+ * Get the default session storage directory.
19380
+ */
19381
+ getDefaultDir() {
19382
+ const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
19383
+ return join(home, ".tinycloud", "sessions");
19384
+ }
19385
+ /**
19386
+ * Ensure the storage directory exists.
19387
+ */
19388
+ ensureDirectoryExists() {
19389
+ if (!existsSync(this.baseDir)) {
19390
+ mkdirSync(this.baseDir, { recursive: true });
19391
+ }
19392
+ }
19393
+ /**
19394
+ * Get the file path for an address.
19395
+ */
19396
+ getFilePath(address) {
19397
+ const normalizedAddress = address.toLowerCase();
19398
+ const filename = `${normalizedAddress.replace("0x", "")}.json`;
19399
+ return join(this.baseDir, filename);
19400
+ }
19401
+ /**
19402
+ * Save a session for an address.
19403
+ */
19404
+ async save(address, session) {
19405
+ const filePath = this.getFilePath(address);
19406
+ const data = JSON.stringify(session, null, 2);
19407
+ writeFileSync(filePath, data, "utf-8");
19408
+ }
19409
+ /**
19410
+ * Load a session for an address.
19411
+ */
19412
+ async load(address) {
19413
+ const filePath = this.getFilePath(address);
19414
+ if (!existsSync(filePath)) {
19415
+ return null;
19416
+ }
19417
+ try {
19418
+ const data = readFileSync(filePath, "utf-8");
19419
+ const parsed = JSON.parse(data);
19420
+ const validation = validatePersistedSessionData(parsed);
19421
+ if (!validation.ok) {
19422
+ console.warn(`Invalid session data for ${address}:`, validation.error.message);
19423
+ unlinkSync(filePath);
19424
+ return null;
19425
+ }
19426
+ const session = validation.data;
19427
+ const expiresAt = new Date(session.expiresAt);
19428
+ if (expiresAt < /* @__PURE__ */ new Date()) {
19429
+ unlinkSync(filePath);
19430
+ return null;
19431
+ }
19432
+ return session;
19433
+ } catch (error) {
19434
+ try {
19435
+ unlinkSync(filePath);
19436
+ } catch {
19437
+ }
19438
+ return null;
19439
+ }
19440
+ }
19441
+ /**
19442
+ * Clear a session for an address.
19443
+ */
19444
+ async clear(address) {
19445
+ const filePath = this.getFilePath(address);
19446
+ if (existsSync(filePath)) {
19447
+ unlinkSync(filePath);
19448
+ }
19449
+ }
19450
+ /**
19451
+ * Check if a session exists for an address.
19452
+ */
19453
+ exists(address) {
19454
+ const filePath = this.getFilePath(address);
19455
+ if (!existsSync(filePath)) {
19456
+ return false;
19457
+ }
19458
+ try {
19459
+ const data = readFileSync(filePath, "utf-8");
19460
+ const session = JSON.parse(data);
19461
+ const expiresAt = new Date(session.expiresAt);
19462
+ if (expiresAt < /* @__PURE__ */ new Date()) {
19463
+ unlinkSync(filePath);
19464
+ return false;
19465
+ }
19466
+ return true;
19467
+ } catch {
19468
+ return false;
19469
+ }
19470
+ }
19471
+ /**
19472
+ * Check if file system storage is available.
19473
+ */
19474
+ isAvailable() {
19475
+ try {
19476
+ this.ensureDirectoryExists();
19477
+ return existsSync(this.baseDir);
19478
+ } catch {
19479
+ return false;
19480
+ }
19481
+ }
19482
+ };
19188
19483
 
19189
19484
  // src/delegation.ts
19190
19485
  function serializeDelegation(delegation) {
@@ -19206,7 +19501,7 @@ function deserializeDelegation(data) {
19206
19501
  import { KVService as KVService3, PrefixedKVService } from "@tinycloud/sdk-core";
19207
19502
  import { SQLService as SQLService3, SQLAction, DatabaseHandle } from "@tinycloud/sdk-core";
19208
19503
  import { DuckDbService as DuckDbService3, DuckDbDatabaseHandle, DuckDbAction } from "@tinycloud/sdk-core";
19209
- import { DataVaultService as DataVaultService2, VaultAction, VaultHeaders, createVaultCrypto as createVaultCrypto2 } from "@tinycloud/sdk-core";
19504
+ import { DataVaultService as DataVaultService2, VaultHeaders, VaultPublicSpaceKVActions, createVaultCrypto as createVaultCrypto2 } from "@tinycloud/sdk-core";
19210
19505
  import {
19211
19506
  DelegationManager as DelegationManager2,
19212
19507
  SharingService as SharingService2,
@@ -19224,17 +19519,18 @@ import {
19224
19519
  createSpaceService,
19225
19520
  parseSpaceUri,
19226
19521
  buildSpaceUri,
19227
- makePublicSpaceId,
19522
+ makePublicSpaceId as makePublicSpaceId2,
19228
19523
  Space
19229
19524
  } from "@tinycloud/sdk-core";
19230
19525
  import {
19231
19526
  ProtocolMismatchError,
19232
19527
  VersionCheckError,
19233
19528
  UnsupportedFeatureError as UnsupportedFeatureError2,
19234
- checkNodeVersion as checkNodeVersion2
19529
+ checkNodeInfo as checkNodeInfo2
19235
19530
  } from "@tinycloud/sdk-core";
19236
19531
  import { ServiceContext as ServiceContext3 } from "@tinycloud/sdk-core";
19237
19532
  export {
19533
+ AutoApproveSpaceCreationHandler2 as AutoApproveSpaceCreationHandler,
19238
19534
  CapabilityKeyRegistry2 as CapabilityKeyRegistry,
19239
19535
  CapabilityKeyRegistryErrorCodes,
19240
19536
  DataVaultService2 as DataVaultService,
@@ -19249,6 +19545,7 @@ export {
19249
19545
  KVService3 as KVService,
19250
19546
  MemorySessionStorage,
19251
19547
  NodeUserAuthorization,
19548
+ NodeWasmBindings,
19252
19549
  PrefixedKVService,
19253
19550
  PrivateKeySigner,
19254
19551
  ProtocolMismatchError,
@@ -19256,26 +19553,28 @@ export {
19256
19553
  SQLService3 as SQLService,
19257
19554
  ServiceContext3 as ServiceContext,
19258
19555
  SharingService2 as SharingService,
19556
+ SilentNotificationHandler2 as SilentNotificationHandler,
19259
19557
  Space,
19260
19558
  SpaceErrorCodes,
19261
19559
  SpaceService2 as SpaceService,
19262
19560
  TinyCloud2 as TinyCloud,
19263
19561
  TinyCloudNode,
19264
19562
  UnsupportedFeatureError2 as UnsupportedFeatureError,
19265
- VaultAction,
19266
19563
  VaultHeaders,
19564
+ VaultPublicSpaceKVActions,
19267
19565
  VersionCheckError,
19268
19566
  WasmKeyProvider,
19269
19567
  buildSpaceUri,
19270
- checkNodeVersion2 as checkNodeVersion,
19568
+ checkNodeInfo2 as checkNodeInfo,
19271
19569
  createCapabilityKeyRegistry,
19272
19570
  createSharingService,
19273
19571
  createSpaceService,
19274
19572
  createVaultCrypto2 as createVaultCrypto,
19275
19573
  createWasmKeyProvider,
19276
19574
  defaultSignStrategy,
19575
+ defaultSpaceCreationHandler,
19277
19576
  deserializeDelegation,
19278
- makePublicSpaceId,
19577
+ makePublicSpaceId2 as makePublicSpaceId,
19279
19578
  parseSpaceUri,
19280
19579
  serializeDelegation
19281
19580
  };