@tinycloud/node-sdk 1.2.0 → 1.4.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
@@ -17349,6 +17349,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17349
17349
  this.sessionExpirationMs = config.sessionExpirationMs ?? 60 * 60 * 1e3;
17350
17350
  this.autoCreateSpace = config.autoCreateSpace ?? false;
17351
17351
  this.tinycloudHosts = config.tinycloudHosts ?? ["https://node.tinycloud.xyz"];
17352
+ this.enablePublicSpace = config.enablePublicSpace ?? true;
17352
17353
  this.sessionManager = new SessionManager();
17353
17354
  }
17354
17355
  /**
@@ -17380,12 +17381,12 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17380
17381
  * Create the space on the TinyCloud server (host delegation).
17381
17382
  * This registers the user as the owner of the space.
17382
17383
  */
17383
- async hostSpace() {
17384
+ async hostSpace(targetSpaceId) {
17384
17385
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
17385
17386
  throw new Error("Must be signed in to host space");
17386
17387
  }
17387
17388
  const host = this.tinycloudHosts[0];
17388
- const spaceId = this._tinyCloudSession.spaceId;
17389
+ const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
17389
17390
  const peerId = await fetchPeerId(host, spaceId);
17390
17391
  const siwe = generateHostSIWEMessage({
17391
17392
  address: this._address,
@@ -17400,6 +17401,13 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17400
17401
  const result = await submitHostDelegation(host, headers);
17401
17402
  return result.success;
17402
17403
  }
17404
+ /**
17405
+ * Create a specific space on the server via host delegation.
17406
+ * Used for lazy creation of additional spaces (e.g., public).
17407
+ */
17408
+ async hostPublicSpace(spaceId) {
17409
+ return this.hostSpace(spaceId);
17410
+ }
17403
17411
  /**
17404
17412
  * Ensure the user's space exists on the TinyCloud server.
17405
17413
  * Creates the space if it doesn't exist and autoCreateSpace is enabled.
@@ -17413,11 +17421,33 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17413
17421
  throw new Error("Must be signed in to ensure space exists");
17414
17422
  }
17415
17423
  const host = this.tinycloudHosts[0];
17424
+ const primarySpaceId = this._tinyCloudSession.spaceId;
17416
17425
  const result = await activateSessionWithHost(
17417
17426
  host,
17418
17427
  this._tinyCloudSession.delegationHeader
17419
17428
  );
17420
17429
  if (result.success) {
17430
+ const primarySkipped = result.skipped?.includes(primarySpaceId);
17431
+ if (!primarySkipped) {
17432
+ return;
17433
+ }
17434
+ if (!this.autoCreateSpace) {
17435
+ return;
17436
+ }
17437
+ const created = await this.hostSpace();
17438
+ if (!created) {
17439
+ throw new Error(`Failed to create space: ${primarySpaceId}`);
17440
+ }
17441
+ await new Promise((resolve) => setTimeout(resolve, 100));
17442
+ const retryResult = await activateSessionWithHost(
17443
+ host,
17444
+ this._tinyCloudSession.delegationHeader
17445
+ );
17446
+ if (!retryResult.success) {
17447
+ throw new Error(
17448
+ `Failed to activate session after creating space: ${retryResult.error}`
17449
+ );
17450
+ }
17421
17451
  return;
17422
17452
  }
17423
17453
  if (result.status === 404) {
@@ -17426,9 +17456,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17426
17456
  }
17427
17457
  const created = await this.hostSpace();
17428
17458
  if (!created) {
17429
- throw new Error(
17430
- `Failed to create space: ${this._tinyCloudSession.spaceId}`
17431
- );
17459
+ throw new Error(`Failed to create space: ${primarySpaceId}`);
17432
17460
  }
17433
17461
  await new Promise((resolve) => setTimeout(resolve, 100));
17434
17462
  const retryResult = await activateSessionWithHost(
@@ -17496,11 +17524,13 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17496
17524
  siwe: prepared.siwe,
17497
17525
  signature: signature2
17498
17526
  };
17527
+ const spacesMetadata = this.enablePublicSpace ? { public: makeSpaceId(address, chainId, "public") } : void 0;
17499
17528
  const tinyCloudSession = {
17500
17529
  address,
17501
17530
  chainId,
17502
17531
  sessionKey: keyId,
17503
17532
  spaceId,
17533
+ spaces: spacesMetadata,
17504
17534
  delegationCid: session.delegationCid,
17505
17535
  delegationHeader: session.delegationHeader,
17506
17536
  verificationMethod: this.sessionManager.getDID(keyId),
@@ -17518,6 +17548,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17518
17548
  delegationHeader: session.delegationHeader,
17519
17549
  delegationCid: session.delegationCid,
17520
17550
  spaceId,
17551
+ spaces: spacesMetadata,
17521
17552
  verificationMethod: this.sessionManager.getDID(keyId)
17522
17553
  },
17523
17554
  expiresAt: expirationTime.toISOString(),
@@ -17647,11 +17678,13 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17647
17678
  siwe: prepared.siwe,
17648
17679
  signature: signature2
17649
17680
  };
17681
+ const spacesMetadata = this.enablePublicSpace ? { public: makeSpaceId(address, chainId, "public") } : void 0;
17650
17682
  const tinyCloudSession = {
17651
17683
  address,
17652
17684
  chainId,
17653
17685
  sessionKey: keyId,
17654
17686
  spaceId: prepared.spaceId,
17687
+ spaces: spacesMetadata,
17655
17688
  delegationCid: session.delegationCid,
17656
17689
  delegationHeader: session.delegationHeader,
17657
17690
  verificationMethod: this.sessionManager.getDID(keyId),
@@ -17673,6 +17706,7 @@ var _NodeUserAuthorization = class _NodeUserAuthorization {
17673
17706
  delegationHeader: session.delegationHeader,
17674
17707
  delegationCid: session.delegationCid,
17675
17708
  spaceId: prepared.spaceId,
17709
+ spaces: spacesMetadata,
17676
17710
  verificationMethod: this.sessionManager.getDID(keyId)
17677
17711
  },
17678
17712
  expiresAt,
@@ -17770,6 +17804,8 @@ import {
17770
17804
  activateSessionWithHost as activateSessionWithHost2,
17771
17805
  KVService as KVService2,
17772
17806
  SQLService as SQLService2,
17807
+ DataVaultService,
17808
+ createVaultCrypto,
17773
17809
  ServiceContext as ServiceContext2,
17774
17810
  DelegationManager,
17775
17811
  SpaceService,
@@ -17783,7 +17819,14 @@ import {
17783
17819
  ensureEip55 as ensureEip553,
17784
17820
  invoke as invoke2,
17785
17821
  initPanicHook as initPanicHook2,
17786
- createDelegation
17822
+ createDelegation,
17823
+ vault_encrypt,
17824
+ vault_decrypt,
17825
+ vault_derive_key,
17826
+ vault_x25519_from_seed,
17827
+ vault_x25519_dh,
17828
+ vault_random_bytes,
17829
+ vault_sha256
17787
17830
  } from "@tinycloud/node-sdk-wasm";
17788
17831
 
17789
17832
  // src/DelegatedAccess.ts
@@ -18015,7 +18058,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18015
18058
  spacePrefix: config.prefix,
18016
18059
  sessionExpirationMs: config.sessionExpirationMs ?? 60 * 60 * 1e3,
18017
18060
  tinycloudHosts: [host],
18018
- autoCreateSpace: config.autoCreateSpace
18061
+ autoCreateSpace: config.autoCreateSpace,
18062
+ enablePublicSpace: config.enablePublicSpace ?? true
18019
18063
  });
18020
18064
  this.tc = new TinyCloud(this.auth);
18021
18065
  }
@@ -18089,6 +18133,46 @@ var _TinyCloudNode = class _TinyCloudNode {
18089
18133
  await this.tc.signIn();
18090
18134
  this.initializeServices();
18091
18135
  }
18136
+ /**
18137
+ * Restore a previously established session from stored delegation data.
18138
+ *
18139
+ * This is used by the CLI to restore a session that was created via the
18140
+ * browser-based delegation flow (OpenKey `/delegate` page). Instead of
18141
+ * signing in with a private key, it injects the delegation data directly.
18142
+ *
18143
+ * @param sessionData - The stored delegation data from the browser flow
18144
+ */
18145
+ async restoreSession(sessionData) {
18146
+ this._kv = void 0;
18147
+ this._sql = void 0;
18148
+ this._serviceContext = void 0;
18149
+ if (sessionData.address) {
18150
+ this._address = sessionData.address;
18151
+ }
18152
+ if (sessionData.chainId) {
18153
+ this._chainId = sessionData.chainId;
18154
+ }
18155
+ this._serviceContext = new ServiceContext2({
18156
+ invoke: invoke2,
18157
+ fetch: globalThis.fetch.bind(globalThis),
18158
+ hosts: [this.config.host]
18159
+ });
18160
+ this._kv = new KVService2({});
18161
+ this._kv.initialize(this._serviceContext);
18162
+ this._serviceContext.registerService("kv", this._kv);
18163
+ this._sql = new SQLService2({});
18164
+ this._sql.initialize(this._serviceContext);
18165
+ this._serviceContext.registerService("sql", this._sql);
18166
+ const serviceSession = {
18167
+ delegationHeader: sessionData.delegationHeader,
18168
+ delegationCid: sessionData.delegationCid,
18169
+ spaceId: sessionData.spaceId,
18170
+ verificationMethod: sessionData.verificationMethod,
18171
+ jwk: sessionData.jwk
18172
+ };
18173
+ this._serviceContext.setSession(serviceSession);
18174
+ this.initializeV2Services(serviceSession);
18175
+ }
18092
18176
  /**
18093
18177
  * Connect a wallet to upgrade from session-only mode to wallet mode.
18094
18178
  *
@@ -18130,7 +18214,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18130
18214
  spacePrefix: prefix,
18131
18215
  sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
18132
18216
  tinycloudHosts: [host],
18133
- autoCreateSpace: this.config.autoCreateSpace
18217
+ autoCreateSpace: this.config.autoCreateSpace,
18218
+ enablePublicSpace: this.config.enablePublicSpace ?? true
18134
18219
  });
18135
18220
  this.tc = new TinyCloud(this.auth);
18136
18221
  this.config.prefix = prefix;
@@ -18144,6 +18229,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18144
18229
  if (!session) {
18145
18230
  return;
18146
18231
  }
18232
+ this.tc.initializeServices(invoke2, [this.config.host]);
18147
18233
  this._serviceContext = new ServiceContext2({
18148
18234
  invoke: invoke2,
18149
18235
  fetch: globalThis.fetch.bind(globalThis),
@@ -18163,6 +18249,43 @@ var _TinyCloudNode = class _TinyCloudNode {
18163
18249
  jwk: session.jwk
18164
18250
  };
18165
18251
  this._serviceContext.setSession(serviceSession);
18252
+ this.tc.serviceContext.setSession(serviceSession);
18253
+ const vaultCrypto = createVaultCrypto({
18254
+ vault_encrypt,
18255
+ vault_decrypt,
18256
+ vault_derive_key,
18257
+ vault_x25519_from_seed,
18258
+ vault_x25519_dh,
18259
+ vault_random_bytes,
18260
+ vault_sha256
18261
+ });
18262
+ const self2 = this;
18263
+ this._vault = new DataVaultService({
18264
+ spaceId: session.spaceId,
18265
+ crypto: vaultCrypto,
18266
+ tc: {
18267
+ kv: this._kv,
18268
+ ensurePublicSpace: async () => {
18269
+ try {
18270
+ await self2.ensurePublicSpace();
18271
+ return { ok: true, data: void 0 };
18272
+ } catch (error) {
18273
+ return { ok: false, error: { code: "STORAGE_ERROR", message: error instanceof Error ? error.message : String(error), service: "vault" } };
18274
+ }
18275
+ },
18276
+ get publicKV() {
18277
+ return self2._publicKV ?? self2.tc.publicKV;
18278
+ },
18279
+ readPublicSpace: (host, spaceId, key2) => TinyCloud.readPublicSpace(host, spaceId, key2),
18280
+ makePublicSpaceId: TinyCloud.makePublicSpaceId,
18281
+ did: this.did,
18282
+ address: this._address,
18283
+ chainId: this._chainId,
18284
+ hosts: [this.config.host]
18285
+ }
18286
+ });
18287
+ this._vault.initialize(this._serviceContext);
18288
+ this._serviceContext.registerService("vault", this._vault);
18166
18289
  this.initializeV2Services(serviceSession);
18167
18290
  }
18168
18291
  /**
@@ -18203,7 +18326,32 @@ var _TinyCloudNode = class _TinyCloudNode {
18203
18326
  isRevoked: false,
18204
18327
  allowSubDelegation: true
18205
18328
  };
18206
- this._capabilityRegistry.registerKey(sessionKey, [rootDelegation]);
18329
+ const delegations = [rootDelegation];
18330
+ if (tcSession.spaces) {
18331
+ for (const [spaceName, spaceId] of Object.entries(tcSession.spaces)) {
18332
+ delegations.push({
18333
+ cid: tcSession.delegationCid,
18334
+ delegateDID: tcSession.verificationMethod,
18335
+ spaceId,
18336
+ path: "",
18337
+ actions: [
18338
+ "tinycloud.kv/put",
18339
+ "tinycloud.kv/get",
18340
+ "tinycloud.kv/del",
18341
+ "tinycloud.kv/list",
18342
+ "tinycloud.kv/metadata",
18343
+ "tinycloud.sql/read",
18344
+ "tinycloud.sql/write",
18345
+ "tinycloud.sql/admin",
18346
+ "tinycloud.sql/*"
18347
+ ],
18348
+ expiry: this.getSessionExpiry(),
18349
+ isRevoked: false,
18350
+ allowSubDelegation: true
18351
+ });
18352
+ }
18353
+ }
18354
+ this._capabilityRegistry.registerKey(sessionKey, delegations);
18207
18355
  }
18208
18356
  this._delegationManager = new DelegationManager({
18209
18357
  hosts: [this.config.host],
@@ -18221,7 +18369,16 @@ var _TinyCloudNode = class _TinyCloudNode {
18221
18369
  createKVService: (spaceId) => {
18222
18370
  const kvService = new KVService2({});
18223
18371
  if (this._serviceContext) {
18224
- kvService.initialize(this._serviceContext);
18372
+ const spaceScopedContext = new ServiceContext2({
18373
+ invoke: this._serviceContext.invoke,
18374
+ fetch: this._serviceContext.fetch,
18375
+ hosts: this._serviceContext.hosts
18376
+ });
18377
+ const session = this._serviceContext.session;
18378
+ if (session) {
18379
+ spaceScopedContext.setSession({ ...session, spaceId });
18380
+ }
18381
+ kvService.initialize(spaceScopedContext);
18225
18382
  }
18226
18383
  return kvService;
18227
18384
  },
@@ -18356,6 +18513,16 @@ var _TinyCloudNode = class _TinyCloudNode {
18356
18513
  }
18357
18514
  return this._sql;
18358
18515
  }
18516
+ /**
18517
+ * Data Vault operations - client-side encrypted KV storage.
18518
+ * Call `vault.unlock(signer)` after signIn() to derive encryption keys.
18519
+ */
18520
+ get vault() {
18521
+ if (!this._vault) {
18522
+ throw new Error("Not signed in. Call signIn() first.");
18523
+ }
18524
+ return this._vault;
18525
+ }
18359
18526
  // ===========================================================================
18360
18527
  // v2 Service Accessors
18361
18528
  // ===========================================================================
@@ -18529,21 +18696,99 @@ var _TinyCloudNode = class _TinyCloudNode {
18529
18696
  // Public Space Methods
18530
18697
  // ===========================================================================
18531
18698
  /**
18532
- * Ensure the user's public space exists.
18533
- * Creates it via spaces.create('public') if it doesn't.
18534
- * Requires the user to be signed in.
18699
+ * Ensure the user's public space exists and is accessible.
18700
+ * Creates the space and activates a session delegation for it.
18701
+ * This is the trigger for lazy public space creation — call it
18702
+ * before writing to spaces.get('public').kv.
18535
18703
  */
18536
18704
  async ensurePublicSpace() {
18537
- if (!this.tc) {
18705
+ if (!this.auth || !this.session || !this.signer) {
18538
18706
  throw new Error("Not signed in. Call signIn() first.");
18539
18707
  }
18540
- return this.tc.ensurePublicSpace();
18708
+ const publicSpaceId = this.session.spaces?.public;
18709
+ if (!publicSpaceId) {
18710
+ throw new Error("Public space not enabled. Set enablePublicSpace: true in config.");
18711
+ }
18712
+ await this.auth.hostPublicSpace(publicSpaceId);
18713
+ const kvActions = [
18714
+ "tinycloud.kv/put",
18715
+ "tinycloud.kv/get",
18716
+ "tinycloud.kv/del",
18717
+ "tinycloud.kv/list",
18718
+ "tinycloud.kv/metadata"
18719
+ ];
18720
+ const abilities = { kv: { "": kvActions } };
18721
+ const now = /* @__PURE__ */ new Date();
18722
+ const expiryMs = 60 * 60 * 1e3;
18723
+ const expirationTime = new Date(now.getTime() + expiryMs);
18724
+ const prepared = prepareSession2({
18725
+ abilities,
18726
+ address: ensureEip553(this.session.address),
18727
+ chainId: this.session.chainId,
18728
+ domain: new URL(this.config.host).hostname,
18729
+ issuedAt: now.toISOString(),
18730
+ expirationTime: expirationTime.toISOString(),
18731
+ spaceId: publicSpaceId,
18732
+ jwk: this.session.jwk,
18733
+ parents: [this.session.delegationCid]
18734
+ });
18735
+ const signature2 = await this.signer.signMessage(prepared.siwe);
18736
+ const delegationSession = completeSessionSetup2({
18737
+ ...prepared,
18738
+ signature: signature2
18739
+ });
18740
+ const activateResult = await activateSessionWithHost2(
18741
+ this.config.host,
18742
+ delegationSession.delegationHeader
18743
+ );
18744
+ if (!activateResult.success) {
18745
+ throw new Error(`Failed to activate public space delegation: ${activateResult.error}`);
18746
+ }
18747
+ if (this._capabilityRegistry && this.session) {
18748
+ const sessionKey = {
18749
+ id: this.session.sessionKey,
18750
+ did: this.session.verificationMethod,
18751
+ type: "session",
18752
+ jwk: this.session.jwk,
18753
+ priority: 0
18754
+ };
18755
+ this._capabilityRegistry.registerKey(sessionKey, [{
18756
+ cid: delegationSession.delegationCid,
18757
+ delegateDID: this.session.verificationMethod,
18758
+ spaceId: publicSpaceId,
18759
+ path: "",
18760
+ actions: kvActions,
18761
+ expiry: expirationTime,
18762
+ isRevoked: false,
18763
+ allowSubDelegation: true
18764
+ }]);
18765
+ }
18766
+ if (this._serviceContext) {
18767
+ const publicKV = new KVService2({ prefix: "" });
18768
+ const publicContext = new ServiceContext2({
18769
+ invoke: invoke2,
18770
+ fetch: this._serviceContext.fetch,
18771
+ hosts: this._serviceContext.hosts
18772
+ });
18773
+ publicContext.setSession({
18774
+ delegationHeader: delegationSession.delegationHeader,
18775
+ delegationCid: delegationSession.delegationCid,
18776
+ spaceId: publicSpaceId,
18777
+ verificationMethod: this.session.verificationMethod,
18778
+ jwk: this.session.jwk
18779
+ });
18780
+ publicKV.initialize(publicContext);
18781
+ this._publicKV = publicKV;
18782
+ }
18541
18783
  }
18542
18784
  /**
18543
18785
  * Get a KVService scoped to the user's own public space.
18544
18786
  * Writes require authentication (owner/delegate).
18545
18787
  */
18546
18788
  get publicKV() {
18789
+ if (this._publicKV) {
18790
+ return this._publicKV;
18791
+ }
18547
18792
  if (!this.tc) {
18548
18793
  throw new Error("Not signed in. Call signIn() first.");
18549
18794
  }
@@ -18641,7 +18886,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18641
18886
  domain: new URL(this.config.host).hostname,
18642
18887
  issuedAt: now.toISOString(),
18643
18888
  expirationTime: expirationTime.toISOString(),
18644
- spaceId: session.spaceId,
18889
+ spaceId: params.spaceIdOverride ?? session.spaceId,
18645
18890
  delegateUri: params.delegateDID,
18646
18891
  parents: [session.delegationCid]
18647
18892
  });
@@ -18660,7 +18905,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18660
18905
  return {
18661
18906
  cid: delegationSession.delegationCid,
18662
18907
  delegationHeader: delegationSession.delegationHeader,
18663
- spaceId: session.spaceId,
18908
+ spaceId: params.spaceIdOverride ?? session.spaceId,
18664
18909
  path: params.path,
18665
18910
  actions: params.actions,
18666
18911
  disableSubDelegation: params.disableSubDelegation ?? false,
@@ -18874,6 +19119,7 @@ function deserializeDelegation(data) {
18874
19119
  // src/index.ts
18875
19120
  import { KVService as KVService3, PrefixedKVService } from "@tinycloud/sdk-core";
18876
19121
  import { SQLService as SQLService3, SQLAction, DatabaseHandle } from "@tinycloud/sdk-core";
19122
+ import { DataVaultService as DataVaultService2, VaultAction, VaultHeaders, createVaultCrypto as createVaultCrypto2 } from "@tinycloud/sdk-core";
18877
19123
  import {
18878
19124
  DelegationManager as DelegationManager2,
18879
19125
  SharingService as SharingService2,
@@ -18903,6 +19149,7 @@ import { ServiceContext as ServiceContext3 } from "@tinycloud/sdk-core";
18903
19149
  export {
18904
19150
  CapabilityKeyRegistry2 as CapabilityKeyRegistry,
18905
19151
  CapabilityKeyRegistryErrorCodes,
19152
+ DataVaultService2 as DataVaultService,
18906
19153
  DatabaseHandle,
18907
19154
  DelegatedAccess,
18908
19155
  DelegationErrorCodes,
@@ -18923,6 +19170,8 @@ export {
18923
19170
  SpaceService2 as SpaceService,
18924
19171
  TinyCloud2 as TinyCloud,
18925
19172
  TinyCloudNode,
19173
+ VaultAction,
19174
+ VaultHeaders,
18926
19175
  VersionCheckError,
18927
19176
  WasmKeyProvider,
18928
19177
  buildSpaceUri,
@@ -18930,6 +19179,7 @@ export {
18930
19179
  createCapabilityKeyRegistry,
18931
19180
  createSharingService,
18932
19181
  createSpaceService,
19182
+ createVaultCrypto2 as createVaultCrypto,
18933
19183
  createWasmKeyProvider,
18934
19184
  defaultSignStrategy,
18935
19185
  deserializeDelegation,