@tinycloud/sdk-services 2.7.0-beta.3 → 2.7.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/BaseService-BwBU5CQ4.d.cts +158 -0
  2. package/dist/BaseService-CnPTKR5G.d.ts +158 -0
  3. package/dist/encryption/index.cjs +46 -6
  4. package/dist/encryption/index.cjs.map +1 -1
  5. package/dist/encryption/index.d.cts +9 -1
  6. package/dist/encryption/index.d.ts +9 -1
  7. package/dist/encryption/index.js +45 -6
  8. package/dist/encryption/index.js.map +1 -1
  9. package/dist/index.cjs +299 -21
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +58 -9
  12. package/dist/index.d.ts +58 -9
  13. package/dist/index.js +293 -18
  14. package/dist/index.js.map +1 -1
  15. package/dist/internal/decrypt-transport-response-error.cjs +38 -0
  16. package/dist/internal/decrypt-transport-response-error.cjs.map +1 -0
  17. package/dist/internal/decrypt-transport-response-error.d.cts +10 -0
  18. package/dist/internal/decrypt-transport-response-error.d.ts +10 -0
  19. package/dist/internal/decrypt-transport-response-error.js +13 -0
  20. package/dist/internal/decrypt-transport-response-error.js.map +1 -0
  21. package/dist/kv/index.cjs +46 -4
  22. package/dist/kv/index.cjs.map +1 -1
  23. package/dist/kv/index.d.cts +2 -1
  24. package/dist/kv/index.d.ts +2 -1
  25. package/dist/kv/index.js +46 -4
  26. package/dist/kv/index.js.map +1 -1
  27. package/dist/sql/index.cjs +6 -2
  28. package/dist/sql/index.cjs.map +1 -1
  29. package/dist/sql/index.d.cts +2 -1
  30. package/dist/sql/index.d.ts +2 -1
  31. package/dist/sql/index.js +6 -2
  32. package/dist/sql/index.js.map +1 -1
  33. package/dist/{BaseService-C-EsEeGo.d.cts → types-DAY1O1kW.d.cts} +12 -156
  34. package/dist/{BaseService-C-EsEeGo.d.ts → types-DAY1O1kW.d.ts} +12 -156
  35. package/package.json +11 -3
@@ -0,0 +1,158 @@
1
+ import { I as IService, a as IServiceContext, S as ServiceSession, b as ServiceError, R as Result } from './types-DAY1O1kW.cjs';
2
+
3
+ /**
4
+ * BaseService - Abstract base class for all TinyCloud services.
5
+ *
6
+ * Provides common functionality:
7
+ * - Context management
8
+ * - Session lifecycle hooks
9
+ * - Abort signal handling
10
+ * - Telemetry emission
11
+ */
12
+
13
+ /**
14
+ * Abstract base class for TinyCloud services.
15
+ *
16
+ * Services extend this class to get common functionality like
17
+ * context management, session lifecycle, and abort handling.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * class MyService extends BaseService implements IMyService {
22
+ * static readonly serviceName = 'myservice';
23
+ *
24
+ * constructor(config: MyServiceConfig = {}) {
25
+ * super();
26
+ * this._config = config;
27
+ * }
28
+ *
29
+ * async doSomething(): Promise<Result<Data>> {
30
+ * if (!this.requireAuth()) {
31
+ * return err(authRequiredError('myservice'));
32
+ * }
33
+ * // ... implementation
34
+ * }
35
+ * }
36
+ * ```
37
+ */
38
+ declare abstract class BaseService implements IService {
39
+ /**
40
+ * Service identifier used for registration.
41
+ * Must be overridden by subclasses.
42
+ */
43
+ static readonly serviceName: string;
44
+ /**
45
+ * Service context providing access to platform dependencies.
46
+ * Set during initialize().
47
+ */
48
+ protected context: IServiceContext;
49
+ /**
50
+ * Abort controller for this service's operations.
51
+ * Reset on sign-out.
52
+ */
53
+ protected abortController: AbortController;
54
+ /**
55
+ * Service-specific configuration.
56
+ */
57
+ protected _config: Record<string, unknown>;
58
+ /**
59
+ * Get the service configuration.
60
+ */
61
+ get config(): Record<string, unknown>;
62
+ /**
63
+ * Initialize the service with context.
64
+ * Called by the SDK after instantiation.
65
+ *
66
+ * @param context - The service context
67
+ */
68
+ initialize(context: IServiceContext): void;
69
+ /**
70
+ * Called when session changes (sign-in, sign-out, refresh).
71
+ * Override in subclasses to handle session changes.
72
+ *
73
+ * @param session - The new session, or null if signed out
74
+ */
75
+ onSessionChange(session: ServiceSession | null): void;
76
+ /**
77
+ * Called when SDK signs out.
78
+ * Aborts all pending operations.
79
+ */
80
+ onSignOut(): void;
81
+ /**
82
+ * Get the abort signal for this service.
83
+ * Combines the service-level abort with context-level abort.
84
+ */
85
+ protected get abortSignal(): AbortSignal;
86
+ /**
87
+ * Check if the service is authenticated.
88
+ */
89
+ protected get isAuthenticated(): boolean;
90
+ /**
91
+ * Get the current session.
92
+ * Throws if not authenticated.
93
+ */
94
+ protected get session(): ServiceSession;
95
+ /**
96
+ * Check authentication and return error result if not authenticated.
97
+ * Use this at the start of methods that require authentication.
98
+ *
99
+ * @returns true if authenticated, false otherwise
100
+ */
101
+ protected requireAuth(): boolean;
102
+ /**
103
+ * Emit a telemetry event.
104
+ *
105
+ * @param event - Event name
106
+ * @param data - Event data
107
+ */
108
+ protected emit(event: string, data: unknown): void;
109
+ /**
110
+ * Emit a service request event.
111
+ *
112
+ * @param action - The action being performed
113
+ * @param key - Optional key/path being accessed
114
+ */
115
+ protected emitRequest(action: string, key?: string): void;
116
+ /**
117
+ * Emit a service response event.
118
+ *
119
+ * @param action - The action that was performed
120
+ * @param ok - Whether the request was successful
121
+ * @param startTime - Start time for duration calculation
122
+ * @param status - Optional HTTP status code
123
+ */
124
+ protected emitResponse(action: string, ok: boolean, startTime: number, status?: number): void;
125
+ /**
126
+ * Emit a service error event.
127
+ *
128
+ * @param error - The service error
129
+ */
130
+ protected emitError(error: ServiceError, action?: string): void;
131
+ /**
132
+ * Get the service name from the static property.
133
+ * Subclasses must define static serviceName.
134
+ */
135
+ protected getServiceName(): string;
136
+ /**
137
+ * Stable span name used by SDK telemetry sinks.
138
+ */
139
+ protected spanName(action: string): string;
140
+ /**
141
+ * Create a combined abort signal from multiple sources.
142
+ *
143
+ * @param signals - Additional abort signals to combine
144
+ * @returns A combined abort signal
145
+ */
146
+ protected combineSignals(...signals: (AbortSignal | undefined)[]): AbortSignal;
147
+ /**
148
+ * Wrap an operation with error handling and telemetry.
149
+ *
150
+ * @param action - The action name for telemetry
151
+ * @param key - Optional key for telemetry
152
+ * @param operation - The operation to execute
153
+ * @returns Result of the operation
154
+ */
155
+ protected withTelemetry<T>(action: string, key: string | undefined, operation: () => Promise<Result<T>>): Promise<Result<T>>;
156
+ }
157
+
158
+ export { BaseService as B };
@@ -0,0 +1,158 @@
1
+ import { I as IService, a as IServiceContext, S as ServiceSession, b as ServiceError, R as Result } from './types-DAY1O1kW.js';
2
+
3
+ /**
4
+ * BaseService - Abstract base class for all TinyCloud services.
5
+ *
6
+ * Provides common functionality:
7
+ * - Context management
8
+ * - Session lifecycle hooks
9
+ * - Abort signal handling
10
+ * - Telemetry emission
11
+ */
12
+
13
+ /**
14
+ * Abstract base class for TinyCloud services.
15
+ *
16
+ * Services extend this class to get common functionality like
17
+ * context management, session lifecycle, and abort handling.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * class MyService extends BaseService implements IMyService {
22
+ * static readonly serviceName = 'myservice';
23
+ *
24
+ * constructor(config: MyServiceConfig = {}) {
25
+ * super();
26
+ * this._config = config;
27
+ * }
28
+ *
29
+ * async doSomething(): Promise<Result<Data>> {
30
+ * if (!this.requireAuth()) {
31
+ * return err(authRequiredError('myservice'));
32
+ * }
33
+ * // ... implementation
34
+ * }
35
+ * }
36
+ * ```
37
+ */
38
+ declare abstract class BaseService implements IService {
39
+ /**
40
+ * Service identifier used for registration.
41
+ * Must be overridden by subclasses.
42
+ */
43
+ static readonly serviceName: string;
44
+ /**
45
+ * Service context providing access to platform dependencies.
46
+ * Set during initialize().
47
+ */
48
+ protected context: IServiceContext;
49
+ /**
50
+ * Abort controller for this service's operations.
51
+ * Reset on sign-out.
52
+ */
53
+ protected abortController: AbortController;
54
+ /**
55
+ * Service-specific configuration.
56
+ */
57
+ protected _config: Record<string, unknown>;
58
+ /**
59
+ * Get the service configuration.
60
+ */
61
+ get config(): Record<string, unknown>;
62
+ /**
63
+ * Initialize the service with context.
64
+ * Called by the SDK after instantiation.
65
+ *
66
+ * @param context - The service context
67
+ */
68
+ initialize(context: IServiceContext): void;
69
+ /**
70
+ * Called when session changes (sign-in, sign-out, refresh).
71
+ * Override in subclasses to handle session changes.
72
+ *
73
+ * @param session - The new session, or null if signed out
74
+ */
75
+ onSessionChange(session: ServiceSession | null): void;
76
+ /**
77
+ * Called when SDK signs out.
78
+ * Aborts all pending operations.
79
+ */
80
+ onSignOut(): void;
81
+ /**
82
+ * Get the abort signal for this service.
83
+ * Combines the service-level abort with context-level abort.
84
+ */
85
+ protected get abortSignal(): AbortSignal;
86
+ /**
87
+ * Check if the service is authenticated.
88
+ */
89
+ protected get isAuthenticated(): boolean;
90
+ /**
91
+ * Get the current session.
92
+ * Throws if not authenticated.
93
+ */
94
+ protected get session(): ServiceSession;
95
+ /**
96
+ * Check authentication and return error result if not authenticated.
97
+ * Use this at the start of methods that require authentication.
98
+ *
99
+ * @returns true if authenticated, false otherwise
100
+ */
101
+ protected requireAuth(): boolean;
102
+ /**
103
+ * Emit a telemetry event.
104
+ *
105
+ * @param event - Event name
106
+ * @param data - Event data
107
+ */
108
+ protected emit(event: string, data: unknown): void;
109
+ /**
110
+ * Emit a service request event.
111
+ *
112
+ * @param action - The action being performed
113
+ * @param key - Optional key/path being accessed
114
+ */
115
+ protected emitRequest(action: string, key?: string): void;
116
+ /**
117
+ * Emit a service response event.
118
+ *
119
+ * @param action - The action that was performed
120
+ * @param ok - Whether the request was successful
121
+ * @param startTime - Start time for duration calculation
122
+ * @param status - Optional HTTP status code
123
+ */
124
+ protected emitResponse(action: string, ok: boolean, startTime: number, status?: number): void;
125
+ /**
126
+ * Emit a service error event.
127
+ *
128
+ * @param error - The service error
129
+ */
130
+ protected emitError(error: ServiceError, action?: string): void;
131
+ /**
132
+ * Get the service name from the static property.
133
+ * Subclasses must define static serviceName.
134
+ */
135
+ protected getServiceName(): string;
136
+ /**
137
+ * Stable span name used by SDK telemetry sinks.
138
+ */
139
+ protected spanName(action: string): string;
140
+ /**
141
+ * Create a combined abort signal from multiple sources.
142
+ *
143
+ * @param signals - Additional abort signals to combine
144
+ * @returns A combined abort signal
145
+ */
146
+ protected combineSignals(...signals: (AbortSignal | undefined)[]): AbortSignal;
147
+ /**
148
+ * Wrap an operation with error handling and telemetry.
149
+ *
150
+ * @param action - The action name for telemetry
151
+ * @param key - Optional key for telemetry
152
+ * @param operation - The operation to execute
153
+ * @returns Result of the operation
154
+ */
155
+ protected withTelemetry<T>(action: string, key: string | undefined, operation: () => Promise<Result<T>>): Promise<Result<T>>;
156
+ }
157
+
158
+ export { BaseService as B };
@@ -25,6 +25,7 @@ __export(encryption_exports, {
25
25
  DECRYPT_RESULT_TYPE: () => DECRYPT_RESULT_TYPE,
26
26
  DEFAULT_ENCRYPTION_ALG: () => DEFAULT_ENCRYPTION_ALG,
27
27
  DEFAULT_KEY_VERSION: () => DEFAULT_KEY_VERSION,
28
+ DecryptTransportResponseError: () => import_decrypt_transport_response_error3.DecryptTransportResponseError,
28
29
  ENCRYPTION_NETWORK_URN_PREFIX: () => ENCRYPTION_NETWORK_URN_PREFIX,
29
30
  ENCRYPTION_SERVICE: () => ENCRYPTION_SERVICE,
30
31
  ENCRYPTION_SERVICE_SHORT: () => ENCRYPTION_SERVICE_SHORT,
@@ -206,7 +207,7 @@ var BaseService = class {
206
207
  * Combines the service-level abort with context-level abort.
207
208
  */
208
209
  get abortSignal() {
209
- return this.abortController.signal;
210
+ return this.combineSignals();
210
211
  }
211
212
  /**
212
213
  * Check if the service is authenticated.
@@ -322,7 +323,11 @@ var BaseService = class {
322
323
  */
323
324
  combineSignals(...signals) {
324
325
  const controller = new AbortController();
325
- const allSignals = [this.abortSignal, ...signals.filter(Boolean)];
326
+ const allSignals = [
327
+ this.abortController.signal,
328
+ this.context?.abortSignal,
329
+ ...signals.filter(Boolean)
330
+ ].filter(Boolean);
326
331
  for (const signal of allSignals) {
327
332
  if (signal.aborted) {
328
333
  controller.abort(signal.reason);
@@ -1209,6 +1214,8 @@ function openWrappedKey(crypto, receiverPrivateKey, response) {
1209
1214
  }
1210
1215
 
1211
1216
  // src/encryption/EncryptionService.ts
1217
+ var import_decrypt_transport_response_error = require("@tinycloud/sdk-services/internal/decrypt-transport-response-error");
1218
+ var import_decrypt_transport_response_error2 = require("@tinycloud/sdk-services/internal/decrypt-transport-response-error");
1212
1219
  function encOk(data) {
1213
1220
  return { ok: true, data };
1214
1221
  }
@@ -1227,17 +1234,20 @@ var EncryptionService = class extends BaseService {
1227
1234
  return this._config.crypto;
1228
1235
  }
1229
1236
  async discoverNetwork(identifier, ownerDid) {
1237
+ this.assertActive();
1230
1238
  const result = await discoverNetwork({
1231
1239
  identifier,
1232
1240
  ...ownerDid !== void 0 ? { ownerDid } : {},
1233
1241
  ...this._config.node !== void 0 ? { node: this._config.node } : {},
1234
1242
  ...this._config.wellKnown !== void 0 ? { wellKnown: this._config.wellKnown } : {}
1235
1243
  });
1244
+ this.assertActive();
1236
1245
  if (!result.ok) return result;
1237
1246
  return encOk(result.data.descriptor);
1238
1247
  }
1239
1248
  async encryptToNetwork(networkId, plaintext, options) {
1240
1249
  try {
1250
+ this.assertActive();
1241
1251
  const discovered = await this.discoverNetwork(networkId);
1242
1252
  if (!discovered.ok) return discovered;
1243
1253
  const usable = ensureNetworkUsableForDecrypt(discovered.data);
@@ -1265,6 +1275,7 @@ var EncryptionService = class extends BaseService {
1265
1275
  }
1266
1276
  async decryptEnvelope(envelope, capabilityProof, options) {
1267
1277
  try {
1278
+ this.assertActive();
1268
1279
  const validated = validateEnvelope(this.crypto, envelope);
1269
1280
  if (!validated.ok) return validated;
1270
1281
  if (options?.aad !== void 0 && validated.data.aad !== base64Encode(options.aad)) {
@@ -1330,16 +1341,38 @@ var EncryptionService = class extends BaseService {
1330
1341
  facts,
1331
1342
  proof: capabilityProof
1332
1343
  });
1333
- if (!built.ok) return built;
1344
+ this.assertActive();
1345
+ if (!built.ok) {
1346
+ if (built.error.code !== "TRANSPORT_ERROR") return built;
1347
+ return encErr(
1348
+ encryptionError({
1349
+ code: "INVALID_INPUT",
1350
+ message: "Unable to build decrypt request"
1351
+ })
1352
+ );
1353
+ }
1334
1354
  let response;
1335
1355
  try {
1336
1356
  response = await this._config.transport.postDecrypt({
1337
1357
  targetNode,
1338
1358
  networkId: envelope.networkId,
1339
1359
  authorization: built.data.authorization,
1340
- canonicalBody: built.data.canonicalBody
1360
+ canonicalBody: built.data.canonicalBody,
1361
+ signal: this.abortSignal
1341
1362
  });
1363
+ this.assertActive();
1342
1364
  } catch (error) {
1365
+ if (error instanceof import_decrypt_transport_response_error.DecryptTransportResponseError) {
1366
+ return encErr(
1367
+ encryptionError(
1368
+ error.status === 401 || error.status === 403 ? {
1369
+ code: "DECRYPT_DENIED",
1370
+ message: "Node denied decrypt request",
1371
+ ...error.permissionHint === void 0 ? {} : { permissionHint: error.permissionHint }
1372
+ } : { code: "INVALID_RESPONSE", message: "Node decrypt request failed" }
1373
+ )
1374
+ );
1375
+ }
1343
1376
  return encErr(
1344
1377
  encryptionError({
1345
1378
  code: "TRANSPORT_ERROR",
@@ -1370,14 +1403,20 @@ var EncryptionService = class extends BaseService {
1370
1403
  } catch (error) {
1371
1404
  return encErr(
1372
1405
  encryptionError({
1373
- code: "TRANSPORT_ERROR",
1374
- cause: toError(error)
1406
+ code: "INVALID_RESPONSE",
1407
+ message: "Local decryption failed"
1375
1408
  })
1376
1409
  );
1377
1410
  }
1378
1411
  }
1412
+ assertActive() {
1413
+ this._config.assertActive?.();
1414
+ }
1379
1415
  };
1380
1416
  EncryptionService.serviceName = "encryption";
1417
+
1418
+ // src/encryption/index.ts
1419
+ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/internal/decrypt-transport-response-error");
1381
1420
  // Annotate the CommonJS export names for ESM import in node:
1382
1421
  0 && (module.exports = {
1383
1422
  DECRYPT_ACTION,
@@ -1385,6 +1424,7 @@ EncryptionService.serviceName = "encryption";
1385
1424
  DECRYPT_RESULT_TYPE,
1386
1425
  DEFAULT_ENCRYPTION_ALG,
1387
1426
  DEFAULT_KEY_VERSION,
1427
+ DecryptTransportResponseError,
1388
1428
  ENCRYPTION_NETWORK_URN_PREFIX,
1389
1429
  ENCRYPTION_SERVICE,
1390
1430
  ENCRYPTION_SERVICE_SHORT,