@recordtimelabel/core 0.4.0 → 0.4.1

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/README.md CHANGED
@@ -17,10 +17,10 @@ During local development an app can consume a sibling checkout with:
17
17
  "@recordtimelabel/core": "file:../recordtimelabel-core"
18
18
  ```
19
19
 
20
- For release builds, consume a fixed npm package, git tag, or private registry version so builds do not depend on a sibling folder path. The durable identity and explicit entrypoint contract is prepared in package version `0.4.0` (publish it before updating consumers):
20
+ For release builds, consume a fixed npm package, git tag, or private registry version so builds do not depend on a sibling folder path. The durable identity and explicit entrypoint contract is prepared in package version `0.4.1` (publish it before updating consumers):
21
21
 
22
22
  ```json
23
- "@recordtimelabel/core": "0.4.0"
23
+ "@recordtimelabel/core": "0.4.1"
24
24
  ```
25
25
 
26
26
  If this checkout's `package.json` is ahead of the published version, publish the new package before updating consumers to that version.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recordtimelabel/core",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "description": "Shared RecordTimeLabel data model, merge logic, operations, and sync engine.",
6
6
  "main": "./src/index.js",
package/src/index.js CHANGED
@@ -17,7 +17,7 @@ const REQUIRED_FOLDERS = [
17
17
  { id: DEFAULT_FOLDER_ID, name: 'Uncategorized' }
18
18
  ];
19
19
 
20
- export const RECORD_TIMELABEL_CORE_VERSION = '0.4.0';
20
+ export const RECORD_TIMELABEL_CORE_VERSION = '0.4.1';
21
21
  export const RTL_SYNC_PROTOCOL_VERSION = 2;
22
22
  export const RTL_MAX_OPERATIONS_PER_REQUEST = 20;
23
23
  export const RTL_MAX_REQUEST_BYTES = 256 * 1024;
@@ -2928,19 +2928,34 @@ const rtlEnvelopeSuccess = (value) => {
2928
2928
  const rtlRetryableEnvelopeError = (value) => {
2929
2929
  const error = value?.error && typeof value.error === 'object' ? value.error : value;
2930
2930
  const status = Number(error?.status ?? error?.statusCode ?? value?.status ?? value?.statusCode);
2931
- const code = String(error?.code ?? value?.code ?? '').toLowerCase();
2931
+ const details = [
2932
+ error?.name,
2933
+ error?.code,
2934
+ error?.reason,
2935
+ error?.message,
2936
+ value?.code,
2937
+ value?.reason,
2938
+ value?.message
2939
+ ].filter(Boolean).join(' ').toLowerCase();
2932
2940
  return Boolean(
2933
2941
  error?.retryable === true ||
2934
2942
  value?.retryable === true ||
2935
2943
  status === 408 || status === 409 || status === 425 || status === 429 || status >= 500 ||
2936
- code === 'bulk_job_in_progress' || code === 'retryable' || code === 'temporarily_unavailable' ||
2937
- code === 'unavailable' || code === 'deadline_exceeded'
2944
+ details.includes('bulk_job_in_progress') || details.includes('retryable') ||
2945
+ details.includes('temporarily_unavailable') || details.includes('unavailable') ||
2946
+ details.includes('deadline_exceeded') || details.includes('failed to fetch') ||
2947
+ details.includes('fetch failed') || details.includes('network-request-failed') ||
2948
+ details.includes('network request failed') || details.includes('network_error') ||
2949
+ details.includes('err_network') || details.includes('econnreset') ||
2950
+ details.includes('etimedout')
2938
2951
  );
2939
2952
  };
2940
2953
 
2941
2954
  const rtlRetryAfterMs = (value) => {
2942
2955
  const error = value?.error && typeof value.error === 'object' ? value.error : value;
2943
- const retryAfter = Number(error?.retryAfterMs ?? value?.retryAfterMs);
2956
+ const rawRetryAfter = error?.retryAfterMs ?? value?.retryAfterMs;
2957
+ if (rawRetryAfter === null || rawRetryAfter === undefined || rawRetryAfter === '') return null;
2958
+ const retryAfter = Number(rawRetryAfter);
2944
2959
  return Number.isFinite(retryAfter) && retryAfter >= 0 ? retryAfter : null;
2945
2960
  };
2946
2961
 
@@ -3265,8 +3280,11 @@ export const createRecordTimeLabelSyncEngine = ({
3265
3280
  const operationRetryAt = (operation, result, retryAfterMs, timestamp) => {
3266
3281
  const direct = Number(result?.nextRetryAt);
3267
3282
  if (Number.isFinite(direct)) return direct;
3268
- const after = Number(result?.retryAfterMs ?? retryAfterMs);
3269
- if (Number.isFinite(after) && after >= 0) return timestamp + after;
3283
+ const rawAfter = result?.retryAfterMs ?? retryAfterMs;
3284
+ if (rawAfter !== null && rawAfter !== undefined && rawAfter !== '') {
3285
+ const after = Number(rawAfter);
3286
+ if (Number.isFinite(after) && after >= 0) return timestamp + after;
3287
+ }
3270
3288
  const attempts = Math.max(0, Number(operation?.retryCount || operation?.retryAttempts || 0));
3271
3289
  return timestamp + Math.min(RTL_RETRY_MAX_MS, RTL_RETRY_BASE_MS * (2 ** attempts));
3272
3290
  };