@g9tm/syncdata 1.4.0 → 1.5.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/PARITY.md CHANGED
@@ -45,7 +45,7 @@ it). This file maps every .NET piece to its twin and lists every deliberate diff
45
45
  | `ExportPendingChangesAsync(path)` | `exportPendingChanges(writeLine)` | the caller writes the lines where it wants |
46
46
  | `CheckIntegrityAsync` | `checkIntegrity()` | |
47
47
  | `G9CSqliteException` (`IG9SyncLocalStoreFailure`) | `G9SqliteStoreError` (`localStoreFailure`) | classified from the driver's code |
48
- | `G9CSignalRSyncTransport`, options | `G9SignalRSyncTransport` (`@g9tm/syncdata/signalr`) | over `G9Client` of `@g9tm/signalr-supernetcore-client`; Lynx: `createLynxSyncTransport` |
48
+ | `G9CSignalRSyncTransport`, options | `G9SignalRSyncTransport` (`@g9tm/syncdata/signalr`) | over `G9Client` of `@g9tm/signalr-supernetcore-client`; Lynx: `createLynxSyncTransport`. Limits (ADR-0074): `CallTimeout` / `PushTimeout` / `StreamIdleTimeout` = `callTimeoutMs` / `pushTimeoutMs` / `streamIdleTimeoutMs`, same defaults, same retryable `G9S-NET-FAILURE`, same connection drop (`SignalRTimeoutTests` / `test/transportTimeouts.test.ts`) |
49
49
  | `G9CInMemorySyncTransport`, `G9CTransportFaults` | `G9FaultInjectingTransport`, `G9TransportFaults` (`@g9tm/syncdata/testing`) | wraps a real transport (no in-process server engine in JavaScript) |
50
50
 
51
51
  ## Deliberate differences
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */
2
- export declare const VERSION = "1.4.0";
2
+ export declare const VERSION = "1.5.0";
3
3
  export { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';
4
4
  export { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException, type G9SyncExceptionOptions } from './abstractions/errors.js';
5
5
  export { G9Long, parseJson, stringifyJson } from './abstractions/long.js';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // doubles `@g9tm/syncdata/testing`, the pure-JavaScript Brotli decoder `@g9tm/syncdata/brotli-js`; Lynx wiring is the
4
4
  // separate package `@g9tm/syncdata-lynx`. Every public type keeps its .NET name without the G9C prefix (PARITY.md).
5
5
  /** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */
6
- export const VERSION = '1.4.0';
6
+ export const VERSION = '1.5.0';
7
7
  // abstractions
8
8
  export { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';
9
9
  export { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException } from './abstractions/errors.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wHAAwH;AACxH,uHAAuH;AACvH,sHAAsH;AACtH,oHAAoH;AAEpH,sGAAsG;AACtG,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACjJ,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAA+B,MAAM,0BAA0B,CAAC;AAC5I,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAElF,WAAW;AACX,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EACL,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACrI,OAAO,EAAE,gBAAgB,EAA4E,MAAM,+BAA+B,CAAC;AAC3I,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,2BAA2B,GAI5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAqB,MAAM,4BAA4B,CAAC;AAE3H,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,wBAAwB,EAAmD,MAAM,mBAAmB,CAAC;AAC9K,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAyB,MAAM,sBAAsB,CAAC;AAC7G,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,oBAAoB,GAYrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,2CAA2C;AAC3C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["// @g9tm/syncdata — the TypeScript twin of the G9SyncData .NET client (abstractions, protocol, engine). The SQLite store\n// is `@g9tm/syncdata/sqlite`, the SignalR transport `@g9tm/syncdata/signalr`, Node helpers `@g9tm/syncdata/node`, test\n// doubles `@g9tm/syncdata/testing`, the pure-JavaScript Brotli decoder `@g9tm/syncdata/brotli-js`; Lynx wiring is the\n// separate package `@g9tm/syncdata-lynx`. Every public type keeps its .NET name without the G9C prefix (PARITY.md).\n\n/** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */\nexport const VERSION = '1.4.0';\n\n// abstractions\nexport { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';\nexport { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException, type G9SyncExceptionOptions } from './abstractions/errors.js';\nexport { G9Long, parseJson, stringifyJson } from './abstractions/long.js';\nexport { EMPTY_GUID, guidToN, newGuid, normalizeGuid, tryNormalizeGuid } from './abstractions/guid.js';\nexport { G9SyncKey } from './abstractions/key.js';\nexport { G9SyncDigest } from './abstractions/digest.js';\nexport { G9SyncParameters, escapeDataString } from './abstractions/parameters.js';\n\n// protocol\nexport * from './protocol/dtos.js';\nexport { G9SyncHubErrors, G9SyncProtocol, negotiateFrameVersion, tableGroup } from './protocol/protocol.js';\nexport {\n bytesField,\n dateTimeMs,\n fromMessagePackNames,\n G9WireGuid,\n GUID_EXTENSION_TYPE,\n readChangesAvailable,\n readContinuation,\n readHelloResult,\n readPullPlan,\n readPushResult,\n readReconcileSummary,\n readSyncChunk,\n toMessagePackNames,\n type G9WireFormat,\n} from './protocol/wire.js';\nexport { G9ECompression, G9EPushRowOp, G9ERowBatchOp, G9RowBatchFormat, G9RowBatchFormatError } from './protocol/rowBatch/format.js';\nexport { G9RowBatchWriter, type G9DateTimeOffsetValue, type G9DateTimeValue, type G9FrameCompressor } from './protocol/rowBatch/writer.js';\nexport {\n G9RowBatchReader,\n getDefaultFrameDecompressor,\n openRowBatch,\n openRowBatchSync,\n readFrameHeader,\n setDefaultFrameDecompressor,\n type G9FrameDecompressor,\n type G9FrameHeader,\n type G9OpenRowBatchOptions,\n} from './protocol/rowBatch/reader.js';\nexport { decimalToDouble, formatDecimal, formatDouble, parseDecimal, type DecimalParts } from './internal/dotnetFormat.js';\n\n// client\nexport { G9SyncClientModel, G9SyncClientModelBuilder, G9SyncClientTable, G9SyncClientTableBuilder, type G9SyncClientColumn, type G9SyncClientIndex } from './client/model.js';\nexport * from './client/storeTypes.js';\nexport type { G9SyncTransport } from './client/transport.js';\nexport { G9ESyncPhase, G9SyncProgressTracker, phaseName, type G9DtSyncProgress } from './client/progress.js';\nexport {\n G9ESyncOutcome,\n G9ESyncPriority,\n G9SyncPostStep,\n G9SyncRun,\n describeModelProblem,\n isTransientError,\n normalizeError,\n outcomeName,\n priorityName,\n resolveEngineOptions,\n type G9RowsAppliedEvent,\n type G9SubscriptionOptions,\n type G9SyncEngineOptions,\n type G9SyncHealth,\n type G9SyncHostHooks,\n type G9SyncLogger,\n type G9SyncLogLevel,\n type G9SyncModelProblem,\n type G9SyncPostStepContext,\n type G9SyncRequest,\n type G9SyncRunResult,\n} from './client/runs.js';\nexport { G9SyncEngine, stageGeneration } from './client/engine.js';\n\n// helpers the Lynx package and tests share\nexport { base64ToBytes, bytesToBase64 } from './internal/base64.js';\nexport { utf8Decode, utf8Encode } from './internal/utf8.js';\nexport { md5 } from './internal/md5.js';\nexport { sha256, toHex } from './internal/sha256.js';\nexport { cancellationError, createAbortController, delay, linkSignals, onAbort, yieldToEventLoop } from './internal/abort.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wHAAwH;AACxH,uHAAuH;AACvH,sHAAsH;AACtH,oHAAoH;AAEpH,sGAAsG;AACtG,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACjJ,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAA+B,MAAM,0BAA0B,CAAC;AAC5I,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAElF,WAAW;AACX,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EACL,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACrI,OAAO,EAAE,gBAAgB,EAA4E,MAAM,+BAA+B,CAAC;AAC3I,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,2BAA2B,GAI5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAqB,MAAM,4BAA4B,CAAC;AAE3H,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,wBAAwB,EAAmD,MAAM,mBAAmB,CAAC;AAC9K,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAyB,MAAM,sBAAsB,CAAC;AAC7G,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,oBAAoB,GAYrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,2CAA2C;AAC3C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["// @g9tm/syncdata — the TypeScript twin of the G9SyncData .NET client (abstractions, protocol, engine). The SQLite store\n// is `@g9tm/syncdata/sqlite`, the SignalR transport `@g9tm/syncdata/signalr`, Node helpers `@g9tm/syncdata/node`, test\n// doubles `@g9tm/syncdata/testing`, the pure-JavaScript Brotli decoder `@g9tm/syncdata/brotli-js`; Lynx wiring is the\n// separate package `@g9tm/syncdata-lynx`. Every public type keeps its .NET name without the G9C prefix (PARITY.md).\n\n/** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */\nexport const VERSION = '1.5.0';\n\n// abstractions\nexport { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';\nexport { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException, type G9SyncExceptionOptions } from './abstractions/errors.js';\nexport { G9Long, parseJson, stringifyJson } from './abstractions/long.js';\nexport { EMPTY_GUID, guidToN, newGuid, normalizeGuid, tryNormalizeGuid } from './abstractions/guid.js';\nexport { G9SyncKey } from './abstractions/key.js';\nexport { G9SyncDigest } from './abstractions/digest.js';\nexport { G9SyncParameters, escapeDataString } from './abstractions/parameters.js';\n\n// protocol\nexport * from './protocol/dtos.js';\nexport { G9SyncHubErrors, G9SyncProtocol, negotiateFrameVersion, tableGroup } from './protocol/protocol.js';\nexport {\n bytesField,\n dateTimeMs,\n fromMessagePackNames,\n G9WireGuid,\n GUID_EXTENSION_TYPE,\n readChangesAvailable,\n readContinuation,\n readHelloResult,\n readPullPlan,\n readPushResult,\n readReconcileSummary,\n readSyncChunk,\n toMessagePackNames,\n type G9WireFormat,\n} from './protocol/wire.js';\nexport { G9ECompression, G9EPushRowOp, G9ERowBatchOp, G9RowBatchFormat, G9RowBatchFormatError } from './protocol/rowBatch/format.js';\nexport { G9RowBatchWriter, type G9DateTimeOffsetValue, type G9DateTimeValue, type G9FrameCompressor } from './protocol/rowBatch/writer.js';\nexport {\n G9RowBatchReader,\n getDefaultFrameDecompressor,\n openRowBatch,\n openRowBatchSync,\n readFrameHeader,\n setDefaultFrameDecompressor,\n type G9FrameDecompressor,\n type G9FrameHeader,\n type G9OpenRowBatchOptions,\n} from './protocol/rowBatch/reader.js';\nexport { decimalToDouble, formatDecimal, formatDouble, parseDecimal, type DecimalParts } from './internal/dotnetFormat.js';\n\n// client\nexport { G9SyncClientModel, G9SyncClientModelBuilder, G9SyncClientTable, G9SyncClientTableBuilder, type G9SyncClientColumn, type G9SyncClientIndex } from './client/model.js';\nexport * from './client/storeTypes.js';\nexport type { G9SyncTransport } from './client/transport.js';\nexport { G9ESyncPhase, G9SyncProgressTracker, phaseName, type G9DtSyncProgress } from './client/progress.js';\nexport {\n G9ESyncOutcome,\n G9ESyncPriority,\n G9SyncPostStep,\n G9SyncRun,\n describeModelProblem,\n isTransientError,\n normalizeError,\n outcomeName,\n priorityName,\n resolveEngineOptions,\n type G9RowsAppliedEvent,\n type G9SubscriptionOptions,\n type G9SyncEngineOptions,\n type G9SyncHealth,\n type G9SyncHostHooks,\n type G9SyncLogger,\n type G9SyncLogLevel,\n type G9SyncModelProblem,\n type G9SyncPostStepContext,\n type G9SyncRequest,\n type G9SyncRunResult,\n} from './client/runs.js';\nexport { G9SyncEngine, stageGeneration } from './client/engine.js';\n\n// helpers the Lynx package and tests share\nexport { base64ToBytes, bytesToBase64 } from './internal/base64.js';\nexport { utf8Decode, utf8Encode } from './internal/utf8.js';\nexport { md5 } from './internal/md5.js';\nexport { sha256, toHex } from './internal/sha256.js';\nexport { cancellationError, createAbortController, delay, linkSignals, onAbort, yieldToEventLoop } from './internal/abort.js';\n"]}
@@ -25,6 +25,19 @@ export interface G9SignalRSyncTransportOptions {
25
25
  connectTimeoutMs?: number;
26
26
  serverTimeoutMs?: number;
27
27
  keepAliveIntervalMs?: number;
28
+ /**
29
+ * How long a single-answer call (Hello, PlanPull) waits for its answer before it is a retryable G9S-NET-FAILURE (ADR-0074).
30
+ * Default 60000; 0 = no limit. A live connection does not guarantee an answer: pings keep it up while the call's message
31
+ * was lost on the way.
32
+ */
33
+ callTimeoutMs?: number;
34
+ /** How long a push may take from its first chunk to its result; a safety net, not a pace. Default 600000; 0 = no limit. */
35
+ pushTimeoutMs?: number;
36
+ /**
37
+ * How long a server stream (Pull, Reconcile, FetchRows) may go without a chunk before it is a retryable G9S-NET-FAILURE; the
38
+ * engine resumes from its last continuation. Default 120000 (a snapshot file may still be building); 0 = no limit (ADR-0074).
39
+ */
40
+ streamIdleTimeoutMs?: number;
28
41
  /**
29
42
  * Everything else the G9 client takes (transport, headers, WebSocket constructor, skipNegotiation, reconnect policy, log
30
43
  * level…) — the twin of ConfigureHttpConnection/ConfigureBuilder. `url`, `protocol` and the timeouts above win.
@@ -55,7 +68,10 @@ export declare class G9SignalRSyncTransport implements G9SyncTransport {
55
68
  dispose(): Promise<void>;
56
69
  private _wire;
57
70
  private _read;
71
+ private _callTimeoutMs;
58
72
  private _invoke;
73
+ /** Ends the connection after a call or stream ran out of time (ADR-0074); the next call connects afresh. Never throws. */
74
+ private _dropConnection;
59
75
  private _stream;
60
76
  private _onChanges;
61
77
  }
@@ -98,11 +98,12 @@ export class G9SignalRSyncTransport {
98
98
  }
99
99
  }
100
100
  hello(request, signal) {
101
- return this._invoke(G9SyncProtocol.Methods.Hello, [this._wire(request)], readHelloResult, signal);
101
+ return this._invoke(G9SyncProtocol.Methods.Hello, [this._wire(request)], readHelloResult, this._callTimeoutMs(), signal);
102
102
  }
103
103
  push(request, chunks, signal) {
104
+ var _a;
104
105
  const subject = new Subject();
105
- const result = this._invoke(G9SyncProtocol.Methods.Push, [this._wire(request), subject], readPushResult, signal);
106
+ const result = this._invoke(G9SyncProtocol.Methods.Push, [this._wire(request), subject], readPushResult, (_a = this._options.pushTimeoutMs) !== null && _a !== void 0 ? _a : 600000, signal);
106
107
  void (async () => {
107
108
  try {
108
109
  for await (const chunk of chunks)
@@ -116,7 +117,7 @@ export class G9SignalRSyncTransport {
116
117
  return result;
117
118
  }
118
119
  planPull(request, signal) {
119
- return this._invoke(G9SyncProtocol.Methods.PlanPull, [this._wire(request)], readPullPlan, signal);
120
+ return this._invoke(G9SyncProtocol.Methods.PlanPull, [this._wire(request)], readPullPlan, this._callTimeoutMs(), signal);
120
121
  }
121
122
  pull(token, continuation, signal) {
122
123
  return this._stream(G9SyncProtocol.Methods.Pull, [token, continuation === null ? null : this._wire(continuation)], signal);
@@ -138,33 +139,64 @@ export class G9SignalRSyncTransport {
138
139
  _read(value) {
139
140
  return this.format === 'messagepack' ? fromMessagePackNames(value) : value;
140
141
  }
141
- async _invoke(method, args, read, signal) {
142
+ _callTimeoutMs() {
143
+ var _a;
144
+ return (_a = this._options.callTimeoutMs) !== null && _a !== void 0 ? _a : 60000;
145
+ }
146
+ async _invoke(method, args, read, timeoutMs, signal) {
142
147
  var _a;
143
148
  if (signal && signal.aborted)
144
149
  throw new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.');
145
150
  let unsubscribe = () => undefined;
151
+ let timer = null;
152
+ let timedOut = false;
146
153
  try {
147
154
  const call = this.client.connection.invoke(method, ...args);
148
- const raw = signal
155
+ const raw = signal || timeoutMs > 0
149
156
  ? await new Promise((resolve, reject) => {
150
- unsubscribe = onAbort(signal, () => reject(new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.')));
157
+ if (signal)
158
+ unsubscribe = onAbort(signal, () => reject(new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.')));
159
+ if (timeoutMs > 0) {
160
+ timer = setTimeout(() => {
161
+ timedOut = true;
162
+ reject(new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync server did not answer ${method} within ${Math.round(timeoutMs / 1000)} s.`, {
163
+ retryable: true,
164
+ }));
165
+ }, timeoutMs);
166
+ }
151
167
  call.then(resolve, reject);
152
168
  })
153
169
  : await call;
154
170
  return read(this._read(raw));
155
171
  }
156
172
  catch (error) {
173
+ // ADR-0074: the answer did not come in time. The connection is not trusted any more (the server runs one invocation per
174
+ // connection at a time, and whatever lost this answer may lose the next): drop it, so the retry runs on a fresh one.
175
+ if (timedOut)
176
+ await this._dropConnection();
157
177
  throw (_a = mapError(error, signal ? signal.aborted : false)) !== null && _a !== void 0 ? _a : error;
158
178
  }
159
179
  finally {
180
+ if (timer !== null)
181
+ clearTimeout(timer);
160
182
  unsubscribe();
161
183
  }
162
184
  }
185
+ /** Ends the connection after a call or stream ran out of time (ADR-0074); the next call connects afresh. Never throws. */
186
+ async _dropConnection() {
187
+ try {
188
+ await this.client.connection.stop();
189
+ }
190
+ catch {
191
+ // Stopping a connection that is already gone may throw; the next call connects afresh either way.
192
+ }
193
+ }
163
194
  _stream(method, args, signal) {
164
195
  // eslint-disable-next-line @typescript-eslint/no-this-alias
165
196
  const self = this;
166
197
  return {
167
198
  [Symbol.asyncIterator]() {
199
+ var _a;
168
200
  const queue = [];
169
201
  let done = false;
170
202
  let failure = null;
@@ -177,6 +209,32 @@ export class G9SignalRSyncTransport {
177
209
  w();
178
210
  };
179
211
  let unsubscribeAbort = () => undefined;
212
+ // ADR-0074: the idle limit runs only while the iterator waits for the next chunk, never while the caller processes one.
213
+ const idleMs = (_a = self._options.streamIdleTimeoutMs) !== null && _a !== void 0 ? _a : 120000;
214
+ let idleTimer = null;
215
+ let idleExpired = false;
216
+ const stopIdle = () => {
217
+ if (idleTimer !== null)
218
+ clearTimeout(idleTimer);
219
+ idleTimer = null;
220
+ };
221
+ const armIdle = () => {
222
+ stopIdle();
223
+ if (idleMs <= 0 || done)
224
+ return;
225
+ idleTimer = setTimeout(() => {
226
+ idleTimer = null;
227
+ if (done)
228
+ return;
229
+ idleExpired = true;
230
+ failure = new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync server sent nothing on ${method} for ${Math.round(idleMs / 1000)} s.`, {
231
+ retryable: true,
232
+ });
233
+ done = true;
234
+ subscription === null || subscription === void 0 ? void 0 : subscription.dispose();
235
+ notify();
236
+ }, idleMs);
237
+ };
180
238
  const start = () => {
181
239
  if (subscription || done)
182
240
  return;
@@ -212,6 +270,7 @@ export class G9SignalRSyncTransport {
212
270
  });
213
271
  };
214
272
  const finish = () => {
273
+ stopIdle();
215
274
  unsubscribeAbort();
216
275
  if (subscription && !done)
217
276
  subscription.dispose();
@@ -223,14 +282,21 @@ export class G9SignalRSyncTransport {
223
282
  start();
224
283
  for (;;) {
225
284
  const item = queue.shift();
226
- if (item)
285
+ if (item) {
286
+ stopIdle();
227
287
  return { value: item, done: false };
288
+ }
228
289
  if (done) {
290
+ stopIdle();
229
291
  unsubscribeAbort();
292
+ if (idleExpired)
293
+ await self._dropConnection();
230
294
  if (failure !== null)
231
295
  throw (_a = mapError(failure, signal ? signal.aborted : false)) !== null && _a !== void 0 ? _a : failure;
232
296
  return { value: undefined, done: true };
233
297
  }
298
+ if (idleTimer === null)
299
+ armIdle();
234
300
  await new Promise((resolve) => {
235
301
  wake = resolve;
236
302
  });
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/signalr/transport.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client.SignalR/G9CSignalRSyncTransport.cs: the sync transport over the G9SignalRSuperNetCore client\n// (its jittered reconnect policy and connection states), every failure surfacing as a G9SyncException with the server's\n// stable code. Lynx hosts build the client with the native WebSocket of @g9tm/signalr-supernetcore-lynx\n// (`createLynxSyncTransport` in @g9tm/syncdata-lynx does).\nimport { G9Client, type G9ClientOptions } from '@g9tm/signalr-supernetcore-client';\nimport { HubConnectionState, Subject, type IHubProtocol, type IStreamResult, type ISubscription } from '@microsoft/signalr';\nimport { G9SyncErrorCodes, G9SyncException, isSyncException } from '../abstractions/errors.js';\nimport { createAbortController, onAbort } from '../internal/abort.js';\nimport type { G9SyncTransport } from '../client/transport.js';\nimport type {\n G9DtChangesAvailable,\n G9DtFetchRowsRequest,\n G9DtHelloRequest,\n G9DtHelloResult,\n G9DtPullContinuation,\n G9DtPullPlan,\n G9DtPullRequest,\n G9DtPushRequest,\n G9DtPushResult,\n G9DtReconcileRequest,\n G9DtSyncChunk,\n} from '../protocol/dtos.js';\nimport { G9SyncHubErrors, G9SyncProtocol } from '../protocol/protocol.js';\nimport {\n fromMessagePackNames,\n readChangesAvailable,\n readHelloResult,\n readPullPlan,\n readPushResult,\n readSyncChunk,\n toMessagePackNames,\n type G9WireFormat,\n} from '../protocol/wire.js';\nimport { createSyncMessagePackProtocol, G9SyncJsonHubProtocol } from './protocols.js';\n\n/** The SignalR hub protocol a client speaks (`G9ESyncHubProtocol`). The server accepts both. */\nexport const G9ESyncHubProtocol = {\n /** Text frames; payloads base64-encoded (+33%). Readable in traces. */\n Json: 0,\n /** Binary frames: payloads as raw bytes. The default. */\n MessagePack: 1,\n} as const;\nexport type G9ESyncHubProtocol = (typeof G9ESyncHubProtocol)[keyof typeof G9ESyncHubProtocol];\n\n/** Options of {@link G9SignalRSyncTransport} (`G9CSignalRSyncTransportOptions`). Durations are milliseconds. */\nexport interface G9SignalRSyncTransportOptions {\n /** Absolute hub URL, e.g. `https://sync.example.com/g9sync`. */\n url: string;\n /** Hub protocol; MessagePack by default. */\n protocol?: G9ESyncHubProtocol;\n /** Supplies the bearer token for every (re)connect. */\n accessTokenFactory?: () => string | Promise<string>;\n /** SignalR stateful reconnect (ADR-0069); off by default, the server must allow it too. */\n statefulReconnect?: boolean;\n /** How long one connect may take before it counts as a network failure. */\n connectTimeoutMs?: number;\n serverTimeoutMs?: number;\n keepAliveIntervalMs?: number;\n /**\n * Everything else the G9 client takes (transport, headers, WebSocket constructor, skipNegotiation, reconnect policy, log\n * level…) — the twin of ConfigureHttpConnection/ConfigureBuilder. `url`, `protocol` and the timeouts above win.\n */\n client?: Partial<G9ClientOptions>;\n /** Builds the client (tests, hosts with their own wiring); `new G9Client(options)` by default. */\n createClient?: (options: G9ClientOptions) => G9Client;\n}\n\n/** The SignalR implementation of {@link G9SyncTransport}. */\nexport class G9SignalRSyncTransport implements G9SyncTransport {\n readonly client: G9Client;\n readonly format: G9WireFormat;\n private readonly _options: G9SignalRSyncTransportOptions;\n private readonly _handlers: ((changes: G9DtChangesAvailable) => void)[] = [];\n private _connecting: Promise<void> | null = null;\n\n constructor(options: G9SignalRSyncTransportOptions) {\n if (!options || typeof options.url !== 'string' || options.url.trim() === '') throw new TypeError('A hub URL is required.');\n this._options = options;\n const json = options.protocol === G9ESyncHubProtocol.Json;\n this.format = json ? 'json' : 'messagepack';\n const protocol: IHubProtocol = json ? new G9SyncJsonHubProtocol() : createSyncMessagePackProtocol();\n const clientOptions: G9ClientOptions = {\n ...(options.client ?? {}),\n url: options.url,\n protocol,\n statefulReconnect: options.statefulReconnect ?? false,\n serverTimeoutMs: options.serverTimeoutMs ?? 30000,\n keepAliveIntervalMs: options.keepAliveIntervalMs ?? 10000,\n };\n if (options.accessTokenFactory) clientOptions.accessTokenFactory = options.accessTokenFactory;\n this.client = options.createClient ? options.createClient(clientOptions) : new G9Client(clientOptions);\n this.client.on(G9SyncProtocol.Listeners.OnChangesAvailable, (payload: unknown) => this._onChanges(payload));\n }\n\n get isConnected(): boolean {\n return this.client.connection.state === HubConnectionState.Connected;\n }\n\n onChangesAvailable(handler: (changes: G9DtChangesAvailable) => void): () => void {\n this._handlers.push(handler);\n return () => {\n const index = this._handlers.indexOf(handler);\n if (index >= 0) this._handlers.splice(index, 1);\n };\n }\n\n /** Connects (joins a connect in progress); a connect that takes longer than connectTimeoutMs is a network failure. */\n connect(signal?: AbortSignal): Promise<void> {\n if (this.isConnected) return Promise.resolve();\n if (!this._connecting) {\n const connecting = this._connectCore().finally(() => {\n if (this._connecting === connecting) this._connecting = null;\n });\n this._connecting = connecting;\n }\n const connecting = this._connecting;\n if (!signal) return connecting;\n return new Promise<void>((resolve, reject) => {\n const unsubscribe = onAbort(signal, () => reject(new G9SyncException(G9SyncErrorCodes.Canceled, 'The connect was canceled.')));\n connecting.then(\n () => {\n unsubscribe();\n resolve();\n },\n (error) => {\n unsubscribe();\n reject(error);\n },\n );\n });\n }\n\n private async _connectCore(): Promise<void> {\n const timeout = createAbortController();\n const timer = setTimeout(() => timeout.abort(), this._options.connectTimeoutMs ?? 20000);\n try {\n await this.client.start(timeout.signal);\n } catch (error) {\n const mapped = mapError(error, false) ?? new G9SyncException(G9SyncErrorCodes.NetworkFailure, messageOf(error), { retryable: true, cause: error });\n throw mapped.code === G9SyncErrorCodes.Canceled\n ? new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync connection to ${this._options.url} did not open in time.`, { retryable: true, cause: error })\n : mapped;\n } finally {\n clearTimeout(timer);\n }\n if (!this.isConnected) {\n throw new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync connection is ${String(this.client.connection.state)}.`, { retryable: true });\n }\n }\n\n hello(request: G9DtHelloRequest, signal?: AbortSignal): Promise<G9DtHelloResult> {\n return this._invoke(G9SyncProtocol.Methods.Hello, [this._wire(request)], readHelloResult, signal);\n }\n\n push(request: G9DtPushRequest, chunks: AsyncIterable<G9DtSyncChunk>, signal?: AbortSignal): Promise<G9DtPushResult> {\n const subject = new Subject<unknown>();\n const result = this._invoke(G9SyncProtocol.Methods.Push, [this._wire(request), subject], readPushResult, signal);\n void (async () => {\n try {\n for await (const chunk of chunks) subject.next(this._wire(chunk));\n subject.complete();\n } catch (error) {\n subject.error(error);\n }\n })();\n return result;\n }\n\n planPull(request: G9DtPullRequest, signal?: AbortSignal): Promise<G9DtPullPlan> {\n return this._invoke(G9SyncProtocol.Methods.PlanPull, [this._wire(request)], readPullPlan, signal);\n }\n\n pull(token: string, continuation: G9DtPullContinuation | null, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n return this._stream(G9SyncProtocol.Methods.Pull, [token, continuation === null ? null : this._wire(continuation)], signal);\n }\n\n reconcile(request: G9DtReconcileRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n return this._stream(G9SyncProtocol.Methods.Reconcile, [this._wire(request)], signal);\n }\n\n fetchRows(request: G9DtFetchRowsRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n return this._stream(G9SyncProtocol.Methods.FetchRows, [this._wire(request)], signal);\n }\n\n async dispose(): Promise<void> {\n this._handlers.length = 0;\n await this.client.stop();\n }\n\n // ================================================================ plumbing\n\n private _wire(value: unknown): unknown {\n return this.format === 'messagepack' ? toMessagePackNames(value) : value;\n }\n\n private _read(value: unknown): unknown {\n return this.format === 'messagepack' ? fromMessagePackNames(value) : value;\n }\n\n private async _invoke<T>(method: string, args: unknown[], read: (value: unknown) => T, signal?: AbortSignal): Promise<T> {\n if (signal && signal.aborted) throw new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.');\n let unsubscribe: () => void = () => undefined;\n try {\n const call = this.client.connection.invoke(method, ...args);\n const raw = signal\n ? await new Promise<unknown>((resolve, reject) => {\n unsubscribe = onAbort(signal, () => reject(new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.')));\n call.then(resolve, reject);\n })\n : await call;\n return read(this._read(raw));\n } catch (error) {\n throw mapError(error, signal ? signal.aborted : false) ?? error;\n } finally {\n unsubscribe();\n }\n }\n\n private _stream(method: string, args: unknown[], signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n return {\n [Symbol.asyncIterator](): AsyncIterator<G9DtSyncChunk> {\n const queue: G9DtSyncChunk[] = [];\n let done = false;\n let failure: unknown = null;\n let wake: (() => void) | null = null;\n let subscription: ISubscription<unknown> | null = null;\n const notify = (): void => {\n const w = wake;\n wake = null;\n if (w) w();\n };\n let unsubscribeAbort: () => void = () => undefined;\n const start = (): void => {\n if (subscription || done) return;\n let stream: IStreamResult<unknown>;\n try {\n stream = self.client.connection.stream(method, ...args);\n } catch (error) {\n failure = error;\n done = true;\n return;\n }\n subscription = stream.subscribe({\n next: (item) => {\n queue.push(readSyncChunk(self._read(item)));\n notify();\n },\n error: (error) => {\n failure = error;\n done = true;\n notify();\n },\n complete: () => {\n done = true;\n notify();\n },\n });\n unsubscribeAbort = onAbort(signal, () => {\n failure = new G9SyncException(G9SyncErrorCodes.Canceled, 'The stream was canceled.');\n done = true;\n subscription?.dispose();\n notify();\n });\n };\n const finish = (): void => {\n unsubscribeAbort();\n if (subscription && !done) subscription.dispose();\n done = true;\n };\n return {\n async next(): Promise<IteratorResult<G9DtSyncChunk>> {\n start();\n for (;;) {\n const item = queue.shift();\n if (item) return { value: item, done: false };\n if (done) {\n unsubscribeAbort();\n if (failure !== null) throw mapError(failure, signal ? signal.aborted : false) ?? failure;\n return { value: undefined as unknown as G9DtSyncChunk, done: true };\n }\n await new Promise<void>((resolve) => {\n wake = resolve;\n });\n }\n },\n async return(): Promise<IteratorResult<G9DtSyncChunk>> {\n finish();\n return { value: undefined as unknown as G9DtSyncChunk, done: true };\n },\n };\n },\n };\n }\n\n private _onChanges(payload: unknown): void {\n const changes = readChangesAvailable(this._read(payload));\n for (const handler of this._handlers.slice()) {\n try {\n handler(changes);\n } catch {\n // A ChangesAvailable handler threw (logged by the .NET transport); it must not break the connection.\n }\n }\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * The sync exception for a transport failure (`Map`): the server's `[G9S|code|retryable]` marker wins; any other hub\n * error is a retryable server error; 401/403 is Unauthorized; the rest is a retryable network failure. Null leaves the\n * error as it is (an already mapped one).\n */\nexport function mapError(error: unknown, canceled: boolean): G9SyncException | null {\n if (isSyncException(error)) return null;\n if (canceled) return new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.', { cause: error });\n const message = messageOf(error);\n const marked = G9SyncHubErrors.tryParse(message);\n if (marked) return marked;\n const status = (error as { statusCode?: unknown }).statusCode;\n if (status === 401 || status === 403) return new G9SyncException(G9SyncErrorCodes.Unauthorized, 'The sync server refused the credentials.', { cause: error });\n if (error instanceof Error && error.name === 'AbortError') return new G9SyncException(G9SyncErrorCodes.Canceled, message, { cause: error });\n // A completion error from the hub: SignalR words it \"An unexpected error occurred invoking '…' on the server.\"\n if (/on the server|HubException/i.test(message)) return new G9SyncException(G9SyncErrorCodes.ServerError, message, { retryable: true, cause: error });\n return new G9SyncException(G9SyncErrorCodes.NetworkFailure, message, { retryable: true, cause: error });\n}\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/signalr/transport.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client.SignalR/G9CSignalRSyncTransport.cs: the sync transport over the G9SignalRSuperNetCore client\n// (its jittered reconnect policy and connection states), every failure surfacing as a G9SyncException with the server's\n// stable code. Lynx hosts build the client with the native WebSocket of @g9tm/signalr-supernetcore-lynx\n// (`createLynxSyncTransport` in @g9tm/syncdata-lynx does).\nimport { G9Client, type G9ClientOptions } from '@g9tm/signalr-supernetcore-client';\nimport { HubConnectionState, Subject, type IHubProtocol, type IStreamResult, type ISubscription } from '@microsoft/signalr';\nimport { G9SyncErrorCodes, G9SyncException, isSyncException } from '../abstractions/errors.js';\nimport { createAbortController, onAbort } from '../internal/abort.js';\nimport type { G9SyncTransport } from '../client/transport.js';\nimport type {\n G9DtChangesAvailable,\n G9DtFetchRowsRequest,\n G9DtHelloRequest,\n G9DtHelloResult,\n G9DtPullContinuation,\n G9DtPullPlan,\n G9DtPullRequest,\n G9DtPushRequest,\n G9DtPushResult,\n G9DtReconcileRequest,\n G9DtSyncChunk,\n} from '../protocol/dtos.js';\nimport { G9SyncHubErrors, G9SyncProtocol } from '../protocol/protocol.js';\nimport {\n fromMessagePackNames,\n readChangesAvailable,\n readHelloResult,\n readPullPlan,\n readPushResult,\n readSyncChunk,\n toMessagePackNames,\n type G9WireFormat,\n} from '../protocol/wire.js';\nimport { createSyncMessagePackProtocol, G9SyncJsonHubProtocol } from './protocols.js';\n\n/** The SignalR hub protocol a client speaks (`G9ESyncHubProtocol`). The server accepts both. */\nexport const G9ESyncHubProtocol = {\n /** Text frames; payloads base64-encoded (+33%). Readable in traces. */\n Json: 0,\n /** Binary frames: payloads as raw bytes. The default. */\n MessagePack: 1,\n} as const;\nexport type G9ESyncHubProtocol = (typeof G9ESyncHubProtocol)[keyof typeof G9ESyncHubProtocol];\n\n/** Options of {@link G9SignalRSyncTransport} (`G9CSignalRSyncTransportOptions`). Durations are milliseconds. */\nexport interface G9SignalRSyncTransportOptions {\n /** Absolute hub URL, e.g. `https://sync.example.com/g9sync`. */\n url: string;\n /** Hub protocol; MessagePack by default. */\n protocol?: G9ESyncHubProtocol;\n /** Supplies the bearer token for every (re)connect. */\n accessTokenFactory?: () => string | Promise<string>;\n /** SignalR stateful reconnect (ADR-0069); off by default, the server must allow it too. */\n statefulReconnect?: boolean;\n /** How long one connect may take before it counts as a network failure. */\n connectTimeoutMs?: number;\n serverTimeoutMs?: number;\n keepAliveIntervalMs?: number;\n /**\n * How long a single-answer call (Hello, PlanPull) waits for its answer before it is a retryable G9S-NET-FAILURE (ADR-0074).\n * Default 60000; 0 = no limit. A live connection does not guarantee an answer: pings keep it up while the call's message\n * was lost on the way.\n */\n callTimeoutMs?: number;\n /** How long a push may take from its first chunk to its result; a safety net, not a pace. Default 600000; 0 = no limit. */\n pushTimeoutMs?: number;\n /**\n * How long a server stream (Pull, Reconcile, FetchRows) may go without a chunk before it is a retryable G9S-NET-FAILURE; the\n * engine resumes from its last continuation. Default 120000 (a snapshot file may still be building); 0 = no limit (ADR-0074).\n */\n streamIdleTimeoutMs?: number;\n /**\n * Everything else the G9 client takes (transport, headers, WebSocket constructor, skipNegotiation, reconnect policy, log\n * level…) — the twin of ConfigureHttpConnection/ConfigureBuilder. `url`, `protocol` and the timeouts above win.\n */\n client?: Partial<G9ClientOptions>;\n /** Builds the client (tests, hosts with their own wiring); `new G9Client(options)` by default. */\n createClient?: (options: G9ClientOptions) => G9Client;\n}\n\n/** The SignalR implementation of {@link G9SyncTransport}. */\nexport class G9SignalRSyncTransport implements G9SyncTransport {\n readonly client: G9Client;\n readonly format: G9WireFormat;\n private readonly _options: G9SignalRSyncTransportOptions;\n private readonly _handlers: ((changes: G9DtChangesAvailable) => void)[] = [];\n private _connecting: Promise<void> | null = null;\n\n constructor(options: G9SignalRSyncTransportOptions) {\n if (!options || typeof options.url !== 'string' || options.url.trim() === '') throw new TypeError('A hub URL is required.');\n this._options = options;\n const json = options.protocol === G9ESyncHubProtocol.Json;\n this.format = json ? 'json' : 'messagepack';\n const protocol: IHubProtocol = json ? new G9SyncJsonHubProtocol() : createSyncMessagePackProtocol();\n const clientOptions: G9ClientOptions = {\n ...(options.client ?? {}),\n url: options.url,\n protocol,\n statefulReconnect: options.statefulReconnect ?? false,\n serverTimeoutMs: options.serverTimeoutMs ?? 30000,\n keepAliveIntervalMs: options.keepAliveIntervalMs ?? 10000,\n };\n if (options.accessTokenFactory) clientOptions.accessTokenFactory = options.accessTokenFactory;\n this.client = options.createClient ? options.createClient(clientOptions) : new G9Client(clientOptions);\n this.client.on(G9SyncProtocol.Listeners.OnChangesAvailable, (payload: unknown) => this._onChanges(payload));\n }\n\n get isConnected(): boolean {\n return this.client.connection.state === HubConnectionState.Connected;\n }\n\n onChangesAvailable(handler: (changes: G9DtChangesAvailable) => void): () => void {\n this._handlers.push(handler);\n return () => {\n const index = this._handlers.indexOf(handler);\n if (index >= 0) this._handlers.splice(index, 1);\n };\n }\n\n /** Connects (joins a connect in progress); a connect that takes longer than connectTimeoutMs is a network failure. */\n connect(signal?: AbortSignal): Promise<void> {\n if (this.isConnected) return Promise.resolve();\n if (!this._connecting) {\n const connecting = this._connectCore().finally(() => {\n if (this._connecting === connecting) this._connecting = null;\n });\n this._connecting = connecting;\n }\n const connecting = this._connecting;\n if (!signal) return connecting;\n return new Promise<void>((resolve, reject) => {\n const unsubscribe = onAbort(signal, () => reject(new G9SyncException(G9SyncErrorCodes.Canceled, 'The connect was canceled.')));\n connecting.then(\n () => {\n unsubscribe();\n resolve();\n },\n (error) => {\n unsubscribe();\n reject(error);\n },\n );\n });\n }\n\n private async _connectCore(): Promise<void> {\n const timeout = createAbortController();\n const timer = setTimeout(() => timeout.abort(), this._options.connectTimeoutMs ?? 20000);\n try {\n await this.client.start(timeout.signal);\n } catch (error) {\n const mapped = mapError(error, false) ?? new G9SyncException(G9SyncErrorCodes.NetworkFailure, messageOf(error), { retryable: true, cause: error });\n throw mapped.code === G9SyncErrorCodes.Canceled\n ? new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync connection to ${this._options.url} did not open in time.`, { retryable: true, cause: error })\n : mapped;\n } finally {\n clearTimeout(timer);\n }\n if (!this.isConnected) {\n throw new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync connection is ${String(this.client.connection.state)}.`, { retryable: true });\n }\n }\n\n hello(request: G9DtHelloRequest, signal?: AbortSignal): Promise<G9DtHelloResult> {\n return this._invoke(G9SyncProtocol.Methods.Hello, [this._wire(request)], readHelloResult, this._callTimeoutMs(), signal);\n }\n\n push(request: G9DtPushRequest, chunks: AsyncIterable<G9DtSyncChunk>, signal?: AbortSignal): Promise<G9DtPushResult> {\n const subject = new Subject<unknown>();\n const result = this._invoke(G9SyncProtocol.Methods.Push, [this._wire(request), subject], readPushResult, this._options.pushTimeoutMs ?? 600000, signal);\n void (async () => {\n try {\n for await (const chunk of chunks) subject.next(this._wire(chunk));\n subject.complete();\n } catch (error) {\n subject.error(error);\n }\n })();\n return result;\n }\n\n planPull(request: G9DtPullRequest, signal?: AbortSignal): Promise<G9DtPullPlan> {\n return this._invoke(G9SyncProtocol.Methods.PlanPull, [this._wire(request)], readPullPlan, this._callTimeoutMs(), signal);\n }\n\n pull(token: string, continuation: G9DtPullContinuation | null, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n return this._stream(G9SyncProtocol.Methods.Pull, [token, continuation === null ? null : this._wire(continuation)], signal);\n }\n\n reconcile(request: G9DtReconcileRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n return this._stream(G9SyncProtocol.Methods.Reconcile, [this._wire(request)], signal);\n }\n\n fetchRows(request: G9DtFetchRowsRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n return this._stream(G9SyncProtocol.Methods.FetchRows, [this._wire(request)], signal);\n }\n\n async dispose(): Promise<void> {\n this._handlers.length = 0;\n await this.client.stop();\n }\n\n // ================================================================ plumbing\n\n private _wire(value: unknown): unknown {\n return this.format === 'messagepack' ? toMessagePackNames(value) : value;\n }\n\n private _read(value: unknown): unknown {\n return this.format === 'messagepack' ? fromMessagePackNames(value) : value;\n }\n\n private _callTimeoutMs(): number {\n return this._options.callTimeoutMs ?? 60000;\n }\n\n private async _invoke<T>(method: string, args: unknown[], read: (value: unknown) => T, timeoutMs: number, signal?: AbortSignal): Promise<T> {\n if (signal && signal.aborted) throw new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.');\n let unsubscribe: () => void = () => undefined;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let timedOut = false;\n try {\n const call = this.client.connection.invoke(method, ...args);\n const raw =\n signal || timeoutMs > 0\n ? await new Promise<unknown>((resolve, reject) => {\n if (signal) unsubscribe = onAbort(signal, () => reject(new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.')));\n if (timeoutMs > 0) {\n timer = setTimeout(() => {\n timedOut = true;\n reject(\n new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync server did not answer ${method} within ${Math.round(timeoutMs / 1000)} s.`, {\n retryable: true,\n }),\n );\n }, timeoutMs);\n }\n call.then(resolve, reject);\n })\n : await call;\n return read(this._read(raw));\n } catch (error) {\n // ADR-0074: the answer did not come in time. The connection is not trusted any more (the server runs one invocation per\n // connection at a time, and whatever lost this answer may lose the next): drop it, so the retry runs on a fresh one.\n if (timedOut) await this._dropConnection();\n throw mapError(error, signal ? signal.aborted : false) ?? error;\n } finally {\n if (timer !== null) clearTimeout(timer);\n unsubscribe();\n }\n }\n\n /** Ends the connection after a call or stream ran out of time (ADR-0074); the next call connects afresh. Never throws. */\n private async _dropConnection(): Promise<void> {\n try {\n await this.client.connection.stop();\n } catch {\n // Stopping a connection that is already gone may throw; the next call connects afresh either way.\n }\n }\n\n private _stream(method: string, args: unknown[], signal?: AbortSignal): AsyncIterable<G9DtSyncChunk> {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n return {\n [Symbol.asyncIterator](): AsyncIterator<G9DtSyncChunk> {\n const queue: G9DtSyncChunk[] = [];\n let done = false;\n let failure: unknown = null;\n let wake: (() => void) | null = null;\n let subscription: ISubscription<unknown> | null = null;\n const notify = (): void => {\n const w = wake;\n wake = null;\n if (w) w();\n };\n let unsubscribeAbort: () => void = () => undefined;\n // ADR-0074: the idle limit runs only while the iterator waits for the next chunk, never while the caller processes one.\n const idleMs = self._options.streamIdleTimeoutMs ?? 120000;\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n let idleExpired = false;\n const stopIdle = (): void => {\n if (idleTimer !== null) clearTimeout(idleTimer);\n idleTimer = null;\n };\n const armIdle = (): void => {\n stopIdle();\n if (idleMs <= 0 || done) return;\n idleTimer = setTimeout(() => {\n idleTimer = null;\n if (done) return;\n idleExpired = true;\n failure = new G9SyncException(G9SyncErrorCodes.NetworkFailure, `The sync server sent nothing on ${method} for ${Math.round(idleMs / 1000)} s.`, {\n retryable: true,\n });\n done = true;\n subscription?.dispose();\n notify();\n }, idleMs);\n };\n const start = (): void => {\n if (subscription || done) return;\n let stream: IStreamResult<unknown>;\n try {\n stream = self.client.connection.stream(method, ...args);\n } catch (error) {\n failure = error;\n done = true;\n return;\n }\n subscription = stream.subscribe({\n next: (item) => {\n queue.push(readSyncChunk(self._read(item)));\n notify();\n },\n error: (error) => {\n failure = error;\n done = true;\n notify();\n },\n complete: () => {\n done = true;\n notify();\n },\n });\n unsubscribeAbort = onAbort(signal, () => {\n failure = new G9SyncException(G9SyncErrorCodes.Canceled, 'The stream was canceled.');\n done = true;\n subscription?.dispose();\n notify();\n });\n };\n const finish = (): void => {\n stopIdle();\n unsubscribeAbort();\n if (subscription && !done) subscription.dispose();\n done = true;\n };\n return {\n async next(): Promise<IteratorResult<G9DtSyncChunk>> {\n start();\n for (;;) {\n const item = queue.shift();\n if (item) {\n stopIdle();\n return { value: item, done: false };\n }\n if (done) {\n stopIdle();\n unsubscribeAbort();\n if (idleExpired) await self._dropConnection();\n if (failure !== null) throw mapError(failure, signal ? signal.aborted : false) ?? failure;\n return { value: undefined as unknown as G9DtSyncChunk, done: true };\n }\n if (idleTimer === null) armIdle();\n await new Promise<void>((resolve) => {\n wake = resolve;\n });\n }\n },\n async return(): Promise<IteratorResult<G9DtSyncChunk>> {\n finish();\n return { value: undefined as unknown as G9DtSyncChunk, done: true };\n },\n };\n },\n };\n }\n\n private _onChanges(payload: unknown): void {\n const changes = readChangesAvailable(this._read(payload));\n for (const handler of this._handlers.slice()) {\n try {\n handler(changes);\n } catch {\n // A ChangesAvailable handler threw (logged by the .NET transport); it must not break the connection.\n }\n }\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * The sync exception for a transport failure (`Map`): the server's `[G9S|code|retryable]` marker wins; any other hub\n * error is a retryable server error; 401/403 is Unauthorized; the rest is a retryable network failure. Null leaves the\n * error as it is (an already mapped one).\n */\nexport function mapError(error: unknown, canceled: boolean): G9SyncException | null {\n if (isSyncException(error)) return null;\n if (canceled) return new G9SyncException(G9SyncErrorCodes.Canceled, 'The call was canceled.', { cause: error });\n const message = messageOf(error);\n const marked = G9SyncHubErrors.tryParse(message);\n if (marked) return marked;\n const status = (error as { statusCode?: unknown }).statusCode;\n if (status === 401 || status === 403) return new G9SyncException(G9SyncErrorCodes.Unauthorized, 'The sync server refused the credentials.', { cause: error });\n if (error instanceof Error && error.name === 'AbortError') return new G9SyncException(G9SyncErrorCodes.Canceled, message, { cause: error });\n // A completion error from the hub: SignalR words it \"An unexpected error occurred invoking '…' on the server.\"\n if (/on the server|HubException/i.test(message)) return new G9SyncException(G9SyncErrorCodes.ServerError, message, { retryable: true, cause: error });\n return new G9SyncException(G9SyncErrorCodes.NetworkFailure, message, { retryable: true, cause: error });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@g9tm/syncdata",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "TypeScript twin of the G9SyncData .NET client for Lynx, Node and browsers: the sync engine, the G9RowBatch protocol, the SQLite client store (same schema as the .NET store) and the SignalR transport.",
5
5
  "license": "MIT",
6
6
  "author": "Iman Kari (G9TM)",