@markwharton/liquidplanner 2.0.1 → 2.1.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
@@ -208,6 +208,8 @@ const client = new LPClient({
208
208
  });
209
209
  ```
210
210
 
211
+ `LPConfig` extends `ClientConfig` from api-core, which provides the `baseUrl`, `onRequest`, and `retry` fields. `apiToken`, `workspaceId`, and `cache` are LP-specific.
212
+
211
213
  ### Cache TTLs
212
214
 
213
215
  | Cache Key | Default TTL |
package/dist/client.js CHANGED
@@ -10,7 +10,7 @@ import { buildAuthHeader, hoursToMinutes, normalizeItemType, filterIs, filterIsN
10
10
  import { buildTree, getTreeAncestors } from './tree.js';
11
11
  import { parseLPErrorResponse } from './errors.js';
12
12
  import { LP_API_BASE } from './constants.js';
13
- import { TTLCache, batchMap, getErrorMessage, fetchWithRetry, ok, err } from '@markwharton/api-core';
13
+ import { TTLCache, batchMap, getErrorMessage, fetchWithRetry, ok, err, resolveRetryConfig } from '@markwharton/api-core';
14
14
  /** Transform raw API item to LPItem, preserving scheduling and effort fields */
15
15
  function transformItem(raw) {
16
16
  const item = {
@@ -126,13 +126,7 @@ export class LPClient {
126
126
  treeTtl: config.cache?.treeTtl ?? 600000,
127
127
  };
128
128
  // Initialize retry config with defaults if provided
129
- if (config.retry) {
130
- this.retryConfig = {
131
- maxRetries: config.retry.maxRetries ?? 3,
132
- initialDelayMs: config.retry.initialDelayMs ?? 1000,
133
- maxDelayMs: config.retry.maxDelayMs ?? 10000,
134
- };
135
- }
129
+ this.retryConfig = resolveRetryConfig(config.retry);
136
130
  }
137
131
  /**
138
132
  * Route through cache if enabled, otherwise call factory directly.
@@ -262,7 +256,7 @@ export class LPClient {
262
256
  return err(`Unexpected response: HTTP ${response.status}`, response.status);
263
257
  }
264
258
  catch (error) {
265
- return err(getErrorMessage(error) || 'Connection failed');
259
+ return err(getErrorMessage(error, 'Connection failed'));
266
260
  }
267
261
  }
268
262
  /**
package/dist/errors.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  * - {"message":"..."} or {"error":"..."}
7
7
  * - Plain text
8
8
  */
9
+ import { ApiError } from '@markwharton/api-core';
9
10
  /**
10
11
  * Parsed LP error response
11
12
  */
@@ -25,14 +26,12 @@ export interface LPParsedError {
25
26
  export declare function parseLPErrorResponse(errorText: string, statusCode: number): LPParsedError;
26
27
  /**
27
28
  * Custom error class for LP API errors
29
+ *
30
+ * Extends ApiError from api-core with LP-specific isDuplicate flag.
28
31
  */
29
- export declare class LPError extends Error {
30
- /** HTTP status code */
31
- status: number;
32
+ export declare class LPError extends ApiError {
32
33
  /** Whether this is a duplicate entry error */
33
34
  isDuplicate: boolean;
34
- /** Raw error response */
35
- rawResponse?: string;
36
35
  constructor(message: string, status: number, options?: {
37
36
  isDuplicate?: boolean;
38
37
  rawResponse?: string;
package/dist/errors.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * - {"message":"..."} or {"error":"..."}
7
7
  * - Plain text
8
8
  */
9
- import { parseJsonErrorResponse } from '@markwharton/api-core';
9
+ import { ApiError, parseJsonErrorResponse } from '@markwharton/api-core';
10
10
  /** Error code for duplicate entry errors */
11
11
  const LP_ERROR_CODE_DUPLICATE = 'duplicate_value';
12
12
  /**
@@ -36,14 +36,14 @@ export function parseLPErrorResponse(errorText, statusCode) {
36
36
  }
37
37
  /**
38
38
  * Custom error class for LP API errors
39
+ *
40
+ * Extends ApiError from api-core with LP-specific isDuplicate flag.
39
41
  */
40
- export class LPError extends Error {
42
+ export class LPError extends ApiError {
41
43
  constructor(message, status, options) {
42
- super(message);
44
+ super(message, status, options);
43
45
  this.name = 'LPError';
44
- this.status = status;
45
46
  this.isDuplicate = options?.isDuplicate ?? false;
46
- this.rawResponse = options?.rawResponse;
47
47
  }
48
48
  /**
49
49
  * Create an LPError from an API response
package/dist/index.d.ts CHANGED
@@ -32,7 +32,7 @@ export { LPClient } from './client.js';
32
32
  export { resolveTaskToAssignment } from './workflows.js';
33
33
  export type { LPConfig, LPCacheConfig, LPRetryConfig, LPItemType, HierarchyItem, LPItem, LPAncestor, LPWorkspace, LPMember, LPCostCode, LPSyncResult, LPTimesheetEntry, LPTimesheetEntryWithId, LPTaskResolution, LPUpsertOptions, LPAssignmentWithContext, LPFindItemsOptions, LPTreeNode, LPWorkspaceTree, } from './types.js';
34
34
  export { ok, err, getErrorMessage } from '@markwharton/api-core';
35
- export type { Result, RetryConfig } from '@markwharton/api-core';
35
+ export type { Result, RetryConfig, OnRequestCallback, ClientConfig } from '@markwharton/api-core';
36
36
  export { hoursToMinutes, normalizeItemType, buildAuthHeader, filterIs, filterIsNot, filterIn, filterGt, filterLt, filterAfter, filterBefore, joinFilters, paginatedFetch, } from './utils.js';
37
37
  export type { PaginateOptions } from './utils.js';
38
38
  export { buildTree, getTreeAncestors, getTreeHierarchyPath, findInTree, } from './tree.js';
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@
32
32
  export { LPClient } from './client.js';
33
33
  // Workflows
34
34
  export { resolveTaskToAssignment } from './workflows.js';
35
- // Re-export Result from api-core
35
+ // Re-exported from @markwharton/api-core
36
36
  export { ok, err, getErrorMessage } from '@markwharton/api-core';
37
37
  // Utilities
38
38
  export { hoursToMinutes, normalizeItemType, buildAuthHeader, filterIs, filterIsNot, filterIn, filterGt, filterLt, filterAfter, filterBefore, joinFilters, paginatedFetch, } from './utils.js';
package/dist/types.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * These types define the data structures used when interacting with
5
5
  * the LiquidPlanner API.
6
6
  */
7
- import type { Result, RetryConfig } from '@markwharton/api-core';
7
+ import type { Result, RetryConfig, ClientConfig } from '@markwharton/api-core';
8
8
  /**
9
9
  * LiquidPlanner item types in the hierarchy
10
10
  */
@@ -199,23 +199,13 @@ export type LPRetryConfig = RetryConfig;
199
199
  /**
200
200
  * LiquidPlanner configuration for API access
201
201
  */
202
- export interface LPConfig {
202
+ export interface LPConfig extends ClientConfig {
203
203
  /** Workspace ID to operate on */
204
204
  workspaceId: number;
205
205
  /** API token for authentication */
206
206
  apiToken: string;
207
- /** Base URL for LP API (defaults to https://next.liquidplanner.com/api) */
208
- baseUrl?: string;
209
- /** Optional callback invoked on each API request (for debugging/logging) */
210
- onRequest?: (info: {
211
- method: string;
212
- url: string;
213
- description?: string;
214
- }) => void;
215
207
  /** Enable caching with optional TTL overrides. Omit to disable caching. */
216
208
  cache?: LPCacheConfig;
217
- /** Retry configuration for transient failures (429, 503). Omit to disable retry. */
218
- retry?: LPRetryConfig;
219
209
  }
220
210
  /**
221
211
  * Result of a timesheet sync operation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markwharton/liquidplanner",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "LiquidPlanner API client for timesheet integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,7 +16,7 @@
16
16
  "clean": "rm -rf dist"
17
17
  },
18
18
  "dependencies": {
19
- "@markwharton/api-core": "^1.1.0"
19
+ "@markwharton/api-core": "^1.2.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^20.10.0",