@spooky-sync/core 0.0.1-canary.373 → 0.0.1-canary.375

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
@@ -569,9 +569,18 @@ const NETWORK_ERROR_PATTERNS = [
569
569
  * which would otherwise hold the outbox's serial lane forever.
570
570
  */
571
571
  const SP00KY_EVENT_POST_FAILED = /error while processing event _00_[^:\s]*: (?:there was an error processing a remote http request: (?:error sending request|5\d\d\b|408\b|429\b)|failed to lookup address information)/;
572
+ /**
573
+ * What the proxy in front of a database answers while the database is away: a
574
+ * restart, or the seconds of a version upgrade. Over HTTP the SDK's error message
575
+ * IS the response body, so these arrive as bare words, and an `application`
576
+ * reading rolls the write back. Anchored: a statement can mention these words,
577
+ * but SurrealDB never answers with nothing else.
578
+ */
579
+ const PROXY_UNAVAILABLE = /^(?:bad gateway|service unavailable|gateway timeout|404 page not found)\s*$/;
572
580
  function classifySyncError(error) {
573
581
  const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
574
582
  if (SP00KY_EVENT_POST_FAILED.test(message)) return "network";
583
+ if (PROXY_UNAVAILABLE.test(message)) return "network";
575
584
  for (const pattern of NETWORK_ERROR_PATTERNS) if (message.includes(pattern)) return "network";
576
585
  return "application";
577
586
  }
@@ -3650,8 +3659,8 @@ function trimHistory(history, cap) {
3650
3659
 
3651
3660
  //#endregion
3652
3661
  //#region src/modules/devtools/index.ts
3653
- const CORE_VERSION = "0.0.1-canary.373";
3654
- const WASM_VERSION = "0.0.1-canary.373";
3662
+ const CORE_VERSION = "0.0.1-canary.375";
3663
+ const WASM_VERSION = "0.0.1-canary.375";
3655
3664
  const SURREAL_VERSION = "3.1.0";
3656
3665
  var DevToolsService = class DevToolsService {
3657
3666
  version = CORE_VERSION;
@@ -17609,7 +17618,7 @@ function createTabsCoordinator(config, s, host) {
17609
17618
  return new TabsCoordinator({
17610
17619
  tabId: s.tabId,
17611
17620
  fingerprint: computeTabsFingerprint({
17612
- coreVersion: "0.0.1-canary.373",
17621
+ coreVersion: "0.0.1-canary.375",
17613
17622
  schemaHash: hash53(config.schemaSurql),
17614
17623
  endpoint: config.database.endpoint ?? "",
17615
17624
  namespace: config.database.namespace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spooky-sync/core",
3
- "version": "0.0.1-canary.373",
3
+ "version": "0.0.1-canary.375",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -75,8 +75,8 @@
75
75
  }
76
76
  },
77
77
  "dependencies": {
78
- "@spooky-sync/query-builder": "0.0.1-canary.373",
79
- "@spooky-sync/ssp-wasm": "0.0.1-canary.373",
78
+ "@spooky-sync/query-builder": "0.0.1-canary.375",
79
+ "@spooky-sync/ssp-wasm": "0.0.1-canary.375",
80
80
  "@sqlite.org/sqlite-wasm": "3.53.0-build1",
81
81
  "@surrealdb/wasm": "^3.1.0",
82
82
  "@surrealdb/wasm-native": "^3.3.4",
@@ -2,6 +2,17 @@ import { describe, it, expect } from 'vitest';
2
2
  import { classifySyncError, isRefusedSessionError } from './error-classification';
3
3
 
4
4
  describe('classifySyncError', () => {
5
+ it('classifies a proxy with no database behind it as network', () => {
6
+ // Over HTTP the SDK's message is the response body. These are Traefik's, while
7
+ // a database restarts or moves in a version upgrade; a rollback would lose the
8
+ // write.
9
+ for (const body of ['Bad Gateway', 'Service Unavailable', 'Gateway Timeout', '404 page not found\n']) {
10
+ expect(classifySyncError(new Error(body))).toBe('network');
11
+ }
12
+ // Only as the whole message: a statement's own error can use the words.
13
+ expect(classifySyncError(new Error('Thrown error: bad gateway to the partner API'))).toBe('application');
14
+ });
15
+
5
16
  it('classifies surreal ConnectionUnavailableError as network', () => {
6
17
  // Thrown synchronously by the WS engine's send() while the socket is down
7
18
  // but reconnect hasn't fired. Message contains "connected", not "connection".
@@ -64,11 +64,21 @@ const NETWORK_ERROR_PATTERNS = [
64
64
  const SP00KY_EVENT_POST_FAILED =
65
65
  /error while processing event _00_[^:\s]*: (?:there was an error processing a remote http request: (?:error sending request|5\d\d\b|408\b|429\b)|failed to lookup address information)/;
66
66
 
67
+ /**
68
+ * What the proxy in front of a database answers while the database is away: a
69
+ * restart, or the seconds of a version upgrade. Over HTTP the SDK's error message
70
+ * IS the response body, so these arrive as bare words, and an `application`
71
+ * reading rolls the write back. Anchored: a statement can mention these words,
72
+ * but SurrealDB never answers with nothing else.
73
+ */
74
+ const PROXY_UNAVAILABLE = /^(?:bad gateway|service unavailable|gateway timeout|404 page not found)\s*$/;
75
+
67
76
  export function classifySyncError(error: unknown): 'network' | 'application' {
68
77
  const message =
69
78
  error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
70
79
 
71
80
  if (SP00KY_EVENT_POST_FAILED.test(message)) return 'network';
81
+ if (PROXY_UNAVAILABLE.test(message)) return 'network';
72
82
 
73
83
  for (const pattern of NETWORK_ERROR_PATTERNS) {
74
84
  if (message.includes(pattern)) {