@g9tm/syncdata 1.5.7 → 1.5.9

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.
@@ -23,7 +23,12 @@ export declare const G9SyncErrorCodes: {
23
23
  readonly TokenExpired: "G9S-TOKEN-EXPIRED";
24
24
  readonly RejectValidation: "G9S-REJ-VALIDATION";
25
25
  readonly RejectConstraint: "G9S-REJ-CONSTRAINT";
26
+ /** No subscription of the caller authorises uploads to the table: passes once the missing subscription is held. */
26
27
  readonly RejectPermission: "G9S-REJ-PERMISSION";
28
+ /** The server's row is outside every subscription the caller may write to (no longer theirs). Since 1.5.9. */
29
+ readonly RejectOutsideScope: "G9S-REJ-OUTSIDE-SCOPE";
30
+ /** After the push the row would be outside every subscription the caller may write to. Since 1.5.9. */
31
+ readonly RejectLeavesScope: "G9S-REJ-LEAVES-SCOPE";
27
32
  readonly RejectDirection: "G9S-REJ-DIRECTION";
28
33
  readonly RejectTooMany: "G9S-REJ-TOO-MANY";
29
34
  /** One row is larger than the server accepts in a push: rejected on the device, every other row still uploads. */
@@ -25,7 +25,12 @@ export const G9SyncErrorCodes = {
25
25
  TokenExpired: 'G9S-TOKEN-EXPIRED',
26
26
  RejectValidation: 'G9S-REJ-VALIDATION',
27
27
  RejectConstraint: 'G9S-REJ-CONSTRAINT',
28
+ /** No subscription of the caller authorises uploads to the table: passes once the missing subscription is held. */
28
29
  RejectPermission: 'G9S-REJ-PERMISSION',
30
+ /** The server's row is outside every subscription the caller may write to (no longer theirs). Since 1.5.9. */
31
+ RejectOutsideScope: 'G9S-REJ-OUTSIDE-SCOPE',
32
+ /** After the push the row would be outside every subscription the caller may write to. Since 1.5.9. */
33
+ RejectLeavesScope: 'G9S-REJ-LEAVES-SCOPE',
29
34
  RejectDirection: 'G9S-REJ-DIRECTION',
30
35
  RejectTooMany: 'G9S-REJ-TOO-MANY',
31
36
  /** One row is larger than the server accepts in a push: rejected on the device, every other row still uploads. */
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/abstractions/errors.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Abstractions/G9SyncErrorCodes.cs and G9CSyncException.cs. A code is a public API: never\r\n// repurpose one, only add — and add it on both sides in the same change.\r\n\r\n/** Stable, support-facing error codes. The client classifies failures by these codes, never by message text. */\r\nexport const G9SyncErrorCodes = {\r\n NetworkFailure: 'G9S-NET-FAILURE',\r\n ServerError: 'G9S-SRV-ERROR',\r\n Canceled: 'G9S-CANCELED',\r\n\r\n Unauthorized: 'G9S-AUTH-401',\r\n UpgradeRequired: 'G9S-VER-UPGRADE',\r\n ProtocolMismatch: 'G9S-VER-PROTOCOL',\r\n\r\n ModelInvalid: 'G9S-MODEL-INVALID',\r\n SchemaUpgradeRequired: 'G9S-SCH-UPGRADE',\r\n UnknownTable: 'G9S-SCH-UNKNOWN-TABLE',\r\n /** A column declared with a type the server's column does not have (ADR-0061): it syncs in neither direction. */\r\n ModelTypeMismatch: 'G9S-MODEL-TYPE-MISMATCH',\r\n /** The server is at its limit of concurrent pulls or pushes (ADR-0062). Retryable. */\r\n ServerBusy: 'G9S-SRV-BUSY',\r\n\r\n UnknownSubscription: 'G9S-SUB-UNKNOWN',\r\n InvalidParameters: 'G9S-SUB-PARAM',\r\n SubscriptionForbidden: 'G9S-SUB-FORBIDDEN',\r\n\r\n ResyncEpoch: 'G9S-RSY-EPOCH',\r\n ResyncHorizon: 'G9S-RSY-HORIZON',\r\n ResyncAuthChanged: 'G9S-RSY-AUTH',\r\n TokenInvalid: 'G9S-TOKEN-INVALID',\r\n TokenExpired: 'G9S-TOKEN-EXPIRED',\r\n\r\n RejectValidation: 'G9S-REJ-VALIDATION',\r\n RejectConstraint: 'G9S-REJ-CONSTRAINT',\r\n RejectPermission: 'G9S-REJ-PERMISSION',\r\n RejectDirection: 'G9S-REJ-DIRECTION',\r\n RejectTooMany: 'G9S-REJ-TOO-MANY',\r\n /** One row is larger than the server accepts in a push: rejected on the device, every other row still uploads. */\r\n RejectTooLarge: 'G9S-REJ-TOO-LARGE',\r\n RejectMalformed: 'G9S-REJ-MALFORMED',\r\n\r\n CommandUnknown: 'G9S-CMD-UNKNOWN',\r\n CommandRejected: 'G9S-CMD-REJECTED',\r\n\r\n ConflictServerWins: 'G9S-CON-SERVER-WINS',\r\n ConflictColumns: 'G9S-CON-COLUMNS',\r\n ConflictDeleted: 'G9S-CON-DELETED',\r\n ConflictResolverRejected: 'G9S-CON-RESOLVER',\r\n\r\n /** The server could not build or serve a planned snapshot file (ADR-0072); the client replans the pull as rows. */\r\n SnapshotFileUnavailable: 'G9S-FILE-UNAVAILABLE',\r\n /** A downloaded snapshot file failed the device's checks; nothing of it was applied and the pull is replanned as rows. */\r\n SnapshotFileCorrupt: 'G9S-FILE-CORRUPT',\r\n LocalStoreError: 'G9S-LOCAL-STORE',\r\n /** The device database is damaged or not a database (ADR-0068). Export what is readable and rebuild from the server. */\r\n LocalStoreCorrupt: 'G9S-LOCAL-CORRUPT',\r\n /** The device ran out of storage while the store was writing. */\r\n LocalStoreDiskFull: 'G9S-LOCAL-DISK-FULL',\r\n /** Another connection held the write lock longer than the busy timeout. Retryable. */\r\n LocalStoreBusy: 'G9S-LOCAL-BUSY',\r\n\r\n Unknown: 'G9S-UNKNOWN',\r\n} as const;\r\n\r\nconst RETRYABLE: { [code: string]: true } = {\r\n 'G9S-NET-FAILURE': true,\r\n 'G9S-SRV-ERROR': true,\r\n 'G9S-SRV-BUSY': true,\r\n 'G9S-TOKEN-EXPIRED': true,\r\n 'G9S-RSY-EPOCH': true,\r\n 'G9S-RSY-HORIZON': true,\r\n 'G9S-RSY-AUTH': true,\r\n 'G9S-LOCAL-BUSY': true,\r\n};\r\n\r\n/** True for failures a later attempt may succeed at without any change to data or code (`G9SyncErrorCodes.IsRetryable`). */\r\nexport function isRetryableCode(code: string): boolean {\r\n return RETRYABLE[code] === true;\r\n}\r\n\r\n/** Options of {@link G9SyncException}. */\r\nexport interface G9SyncExceptionOptions {\r\n /** Overrides the default retryability of the code. */\r\n retryable?: boolean;\r\n /** Structured detail (JSON or text) for logs. Never shown to end users. */\r\n details?: string | null;\r\n /** The underlying failure. */\r\n cause?: unknown;\r\n}\r\n\r\n/**\r\n * The single error type G9SyncData throws for expected failures (twin of `G9CSyncException`). Always carries a stable\r\n * {@link code}; callers switch on the code, never on the message.\r\n */\r\nexport class G9SyncException extends Error {\r\n /** Stable error code (see {@link G9SyncErrorCodes}). */\r\n readonly code: string;\r\n /** True when retrying without changes may succeed. */\r\n readonly retryable: boolean;\r\n /** Optional structured detail (JSON or text) for logs. */\r\n readonly details: string | null;\r\n\r\n constructor(code: string, message: string, options?: G9SyncExceptionOptions) {\r\n super(message);\r\n this.name = 'G9SyncException';\r\n this.code = code;\r\n this.retryable = options?.retryable ?? isRetryableCode(code);\r\n this.details = options?.details ?? null;\r\n if (options && 'cause' in options) {\r\n Object.defineProperty(this, 'cause', { value: options.cause, enumerable: false, writable: true, configurable: true });\r\n }\r\n // ES2019 output: keep instanceof working for subclasses compiled to functions.\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n/** True for a {@link G9SyncException} (also across bundles that each carry a copy of the class). */\r\nexport function isSyncException(error: unknown): error is G9SyncException {\r\n return (\r\n error instanceof G9SyncException ||\r\n (typeof error === 'object' &&\r\n error !== null &&\r\n (error as { name?: unknown }).name === 'G9SyncException' &&\r\n typeof (error as { code?: unknown }).code === 'string')\r\n );\r\n}\r\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/abstractions/errors.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Abstractions/G9SyncErrorCodes.cs and G9CSyncException.cs. A code is a public API: never\r\n// repurpose one, only add — and add it on both sides in the same change.\r\n\r\n/** Stable, support-facing error codes. The client classifies failures by these codes, never by message text. */\r\nexport const G9SyncErrorCodes = {\r\n NetworkFailure: 'G9S-NET-FAILURE',\r\n ServerError: 'G9S-SRV-ERROR',\r\n Canceled: 'G9S-CANCELED',\r\n\r\n Unauthorized: 'G9S-AUTH-401',\r\n UpgradeRequired: 'G9S-VER-UPGRADE',\r\n ProtocolMismatch: 'G9S-VER-PROTOCOL',\r\n\r\n ModelInvalid: 'G9S-MODEL-INVALID',\r\n SchemaUpgradeRequired: 'G9S-SCH-UPGRADE',\r\n UnknownTable: 'G9S-SCH-UNKNOWN-TABLE',\r\n /** A column declared with a type the server's column does not have (ADR-0061): it syncs in neither direction. */\r\n ModelTypeMismatch: 'G9S-MODEL-TYPE-MISMATCH',\r\n /** The server is at its limit of concurrent pulls or pushes (ADR-0062). Retryable. */\r\n ServerBusy: 'G9S-SRV-BUSY',\r\n\r\n UnknownSubscription: 'G9S-SUB-UNKNOWN',\r\n InvalidParameters: 'G9S-SUB-PARAM',\r\n SubscriptionForbidden: 'G9S-SUB-FORBIDDEN',\r\n\r\n ResyncEpoch: 'G9S-RSY-EPOCH',\r\n ResyncHorizon: 'G9S-RSY-HORIZON',\r\n ResyncAuthChanged: 'G9S-RSY-AUTH',\r\n TokenInvalid: 'G9S-TOKEN-INVALID',\r\n TokenExpired: 'G9S-TOKEN-EXPIRED',\r\n\r\n RejectValidation: 'G9S-REJ-VALIDATION',\r\n RejectConstraint: 'G9S-REJ-CONSTRAINT',\r\n /** No subscription of the caller authorises uploads to the table: passes once the missing subscription is held. */\r\n RejectPermission: 'G9S-REJ-PERMISSION',\r\n /** The server's row is outside every subscription the caller may write to (no longer theirs). Since 1.5.9. */\r\n RejectOutsideScope: 'G9S-REJ-OUTSIDE-SCOPE',\r\n /** After the push the row would be outside every subscription the caller may write to. Since 1.5.9. */\r\n RejectLeavesScope: 'G9S-REJ-LEAVES-SCOPE',\r\n RejectDirection: 'G9S-REJ-DIRECTION',\r\n RejectTooMany: 'G9S-REJ-TOO-MANY',\r\n /** One row is larger than the server accepts in a push: rejected on the device, every other row still uploads. */\r\n RejectTooLarge: 'G9S-REJ-TOO-LARGE',\r\n RejectMalformed: 'G9S-REJ-MALFORMED',\r\n\r\n CommandUnknown: 'G9S-CMD-UNKNOWN',\r\n CommandRejected: 'G9S-CMD-REJECTED',\r\n\r\n ConflictServerWins: 'G9S-CON-SERVER-WINS',\r\n ConflictColumns: 'G9S-CON-COLUMNS',\r\n ConflictDeleted: 'G9S-CON-DELETED',\r\n ConflictResolverRejected: 'G9S-CON-RESOLVER',\r\n\r\n /** The server could not build or serve a planned snapshot file (ADR-0072); the client replans the pull as rows. */\r\n SnapshotFileUnavailable: 'G9S-FILE-UNAVAILABLE',\r\n /** A downloaded snapshot file failed the device's checks; nothing of it was applied and the pull is replanned as rows. */\r\n SnapshotFileCorrupt: 'G9S-FILE-CORRUPT',\r\n LocalStoreError: 'G9S-LOCAL-STORE',\r\n /** The device database is damaged or not a database (ADR-0068). Export what is readable and rebuild from the server. */\r\n LocalStoreCorrupt: 'G9S-LOCAL-CORRUPT',\r\n /** The device ran out of storage while the store was writing. */\r\n LocalStoreDiskFull: 'G9S-LOCAL-DISK-FULL',\r\n /** Another connection held the write lock longer than the busy timeout. Retryable. */\r\n LocalStoreBusy: 'G9S-LOCAL-BUSY',\r\n\r\n Unknown: 'G9S-UNKNOWN',\r\n} as const;\r\n\r\nconst RETRYABLE: { [code: string]: true } = {\r\n 'G9S-NET-FAILURE': true,\r\n 'G9S-SRV-ERROR': true,\r\n 'G9S-SRV-BUSY': true,\r\n 'G9S-TOKEN-EXPIRED': true,\r\n 'G9S-RSY-EPOCH': true,\r\n 'G9S-RSY-HORIZON': true,\r\n 'G9S-RSY-AUTH': true,\r\n 'G9S-LOCAL-BUSY': true,\r\n};\r\n\r\n/** True for failures a later attempt may succeed at without any change to data or code (`G9SyncErrorCodes.IsRetryable`). */\r\nexport function isRetryableCode(code: string): boolean {\r\n return RETRYABLE[code] === true;\r\n}\r\n\r\n/** Options of {@link G9SyncException}. */\r\nexport interface G9SyncExceptionOptions {\r\n /** Overrides the default retryability of the code. */\r\n retryable?: boolean;\r\n /** Structured detail (JSON or text) for logs. Never shown to end users. */\r\n details?: string | null;\r\n /** The underlying failure. */\r\n cause?: unknown;\r\n}\r\n\r\n/**\r\n * The single error type G9SyncData throws for expected failures (twin of `G9CSyncException`). Always carries a stable\r\n * {@link code}; callers switch on the code, never on the message.\r\n */\r\nexport class G9SyncException extends Error {\r\n /** Stable error code (see {@link G9SyncErrorCodes}). */\r\n readonly code: string;\r\n /** True when retrying without changes may succeed. */\r\n readonly retryable: boolean;\r\n /** Optional structured detail (JSON or text) for logs. */\r\n readonly details: string | null;\r\n\r\n constructor(code: string, message: string, options?: G9SyncExceptionOptions) {\r\n super(message);\r\n this.name = 'G9SyncException';\r\n this.code = code;\r\n this.retryable = options?.retryable ?? isRetryableCode(code);\r\n this.details = options?.details ?? null;\r\n if (options && 'cause' in options) {\r\n Object.defineProperty(this, 'cause', { value: options.cause, enumerable: false, writable: true, configurable: true });\r\n }\r\n // ES2019 output: keep instanceof working for subclasses compiled to functions.\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n/** True for a {@link G9SyncException} (also across bundles that each carry a copy of the class). */\r\nexport function isSyncException(error: unknown): error is G9SyncException {\r\n return (\r\n error instanceof G9SyncException ||\r\n (typeof error === 'object' &&\r\n error !== null &&\r\n (error as { name?: unknown }).name === 'G9SyncException' &&\r\n typeof (error as { code?: unknown }).code === 'string')\r\n );\r\n}\r\n"]}