@markwharton/liquidplanner 3.1.0 → 3.2.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/dist/client.d.ts +7 -7
- package/dist/client.js +50 -9
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +77 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @see https://api-docs.liquidplanner.com/
|
|
8
8
|
*/
|
|
9
9
|
import type { Result } from '@markwharton/api-core';
|
|
10
|
-
import type { LPConfig, LPWorkspace, LPMember, LPItem, LPCostCode, LPSyncResult, LPTimesheetEntry, LPTimesheetOptions, LPUpsertOptions,
|
|
10
|
+
import type { LPConfig, LPWorkspace, LPMember, LPItem, LPCostCode, LPSyncResult, LPTimesheetEntry, LPTimesheetOptions, LPUpsertOptions, LPAncestor, LPFindItemsOptions, LPWorkspaceTree, LPAssignmentsResult } from './types.js';
|
|
11
11
|
/**
|
|
12
12
|
* LiquidPlanner API Client
|
|
13
13
|
*
|
|
@@ -166,19 +166,19 @@ export declare class LPClient {
|
|
|
166
166
|
*/
|
|
167
167
|
getWorkspaceTree(): Promise<Result<LPWorkspaceTree>>;
|
|
168
168
|
/**
|
|
169
|
-
* Get
|
|
169
|
+
* Get assignments with full context from the workspace tree
|
|
170
|
+
*
|
|
171
|
+
* Returns a normalized result with shared lookup tables for ancestor items
|
|
172
|
+
* and custom field values, reducing payload size for large workspaces.
|
|
170
173
|
*
|
|
171
174
|
* Uses the workspace tree snapshot (cached) to resolve hierarchy locally,
|
|
172
175
|
* eliminating N+1 ancestor request patterns.
|
|
173
176
|
*
|
|
174
177
|
* API calls: 0 (if tree cached) or 1-3 (cold load)
|
|
175
178
|
*
|
|
176
|
-
* @param memberId -
|
|
179
|
+
* @param memberId - Filter to a specific member's assignments. When omitted, returns all members' assignments.
|
|
177
180
|
*/
|
|
178
|
-
getAssignments(memberId
|
|
179
|
-
assignments: LPAssignment[];
|
|
180
|
-
treeItemCount: number;
|
|
181
|
-
}>>;
|
|
181
|
+
getAssignments(memberId?: number): Promise<Result<LPAssignmentsResult>>;
|
|
182
182
|
/**
|
|
183
183
|
* Get all cost codes in the workspace
|
|
184
184
|
*/
|
package/dist/client.js
CHANGED
|
@@ -473,31 +473,62 @@ export class LPClient {
|
|
|
473
473
|
});
|
|
474
474
|
}
|
|
475
475
|
/**
|
|
476
|
-
* Get
|
|
476
|
+
* Get assignments with full context from the workspace tree
|
|
477
|
+
*
|
|
478
|
+
* Returns a normalized result with shared lookup tables for ancestor items
|
|
479
|
+
* and custom field values, reducing payload size for large workspaces.
|
|
477
480
|
*
|
|
478
481
|
* Uses the workspace tree snapshot (cached) to resolve hierarchy locally,
|
|
479
482
|
* eliminating N+1 ancestor request patterns.
|
|
480
483
|
*
|
|
481
484
|
* API calls: 0 (if tree cached) or 1-3 (cold load)
|
|
482
485
|
*
|
|
483
|
-
* @param memberId -
|
|
486
|
+
* @param memberId - Filter to a specific member's assignments. When omitted, returns all members' assignments.
|
|
484
487
|
*/
|
|
485
488
|
async getAssignments(memberId) {
|
|
486
489
|
const treeResult = await this.getWorkspaceTree();
|
|
487
490
|
if (!treeResult.ok)
|
|
488
491
|
return err(treeResult.error, treeResult.status);
|
|
489
492
|
const tree = treeResult.data;
|
|
490
|
-
const
|
|
493
|
+
const items = {};
|
|
494
|
+
const cfvMap = new Map();
|
|
495
|
+
const cfvArray = [];
|
|
496
|
+
const memberMap = new Map();
|
|
491
497
|
for (const node of tree.byId.values()) {
|
|
492
|
-
if (node.itemType !== 'assignments'
|
|
498
|
+
if (node.itemType !== 'assignments')
|
|
499
|
+
continue;
|
|
500
|
+
if (memberId !== undefined && node.userId !== memberId)
|
|
493
501
|
continue;
|
|
494
502
|
const ancestors = getTreeAncestors(tree, node.id);
|
|
495
503
|
const taskAncestor = ancestors.find(a => a.itemType === 'tasks');
|
|
496
504
|
const hierarchyAncestors = ancestors.filter(a => a.itemType === 'projects' || a.itemType === 'folders');
|
|
497
|
-
|
|
498
|
-
const
|
|
505
|
+
// Collect ancestor items into shared lookup
|
|
506
|
+
for (const anc of ancestors) {
|
|
507
|
+
if (!items[anc.id]) {
|
|
508
|
+
const treeNode = tree.byId.get(anc.id);
|
|
509
|
+
items[anc.id] = {
|
|
510
|
+
id: anc.id,
|
|
511
|
+
name: anc.name,
|
|
512
|
+
itemType: anc.itemType,
|
|
513
|
+
parentId: treeNode?.parentId,
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
// Dedup customFieldValues
|
|
518
|
+
const { children: _, customFieldValues, ...itemFields } = node;
|
|
519
|
+
let customFieldValuesIndex;
|
|
520
|
+
if (customFieldValues) {
|
|
521
|
+
const key = JSON.stringify(customFieldValues);
|
|
522
|
+
let idx = cfvMap.get(key);
|
|
523
|
+
if (idx === undefined) {
|
|
524
|
+
idx = cfvArray.length;
|
|
525
|
+
cfvArray.push(customFieldValues);
|
|
526
|
+
cfvMap.set(key, idx);
|
|
527
|
+
}
|
|
528
|
+
customFieldValuesIndex = idx;
|
|
529
|
+
}
|
|
530
|
+
const result = { ...itemFields, customFieldValuesIndex };
|
|
499
531
|
result.taskName = taskAncestor?.name ?? null;
|
|
500
|
-
result.ancestors = ancestors;
|
|
501
532
|
if (hierarchyAncestors.length > 0) {
|
|
502
533
|
result.projectId = hierarchyAncestors[0].id;
|
|
503
534
|
result.projectName = hierarchyAncestors[0].name;
|
|
@@ -508,9 +539,19 @@ export class LPClient {
|
|
|
508
539
|
else {
|
|
509
540
|
result.projectName = null;
|
|
510
541
|
}
|
|
511
|
-
|
|
542
|
+
// Group by member
|
|
543
|
+
const uid = node.userId ?? 0;
|
|
544
|
+
let memberAssignments = memberMap.get(uid);
|
|
545
|
+
if (!memberAssignments) {
|
|
546
|
+
memberAssignments = [];
|
|
547
|
+
memberMap.set(uid, memberAssignments);
|
|
548
|
+
}
|
|
549
|
+
memberAssignments.push(result);
|
|
512
550
|
}
|
|
513
|
-
|
|
551
|
+
const members = [...memberMap.entries()]
|
|
552
|
+
.sort(([a], [b]) => a - b)
|
|
553
|
+
.map(([mid, assignments]) => ({ memberId: mid, assignments }));
|
|
554
|
+
return ok({ members, items, customFieldValues: cfvArray, treeItemCount: tree.itemCount });
|
|
514
555
|
}
|
|
515
556
|
// ============================================================================
|
|
516
557
|
// Cost Codes
|
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*/
|
|
31
31
|
export { LPClient } from './client.js';
|
|
32
32
|
export { resolveTaskToAssignment } from './workflows.js';
|
|
33
|
-
export type { LPConfig, LPCacheConfig, LPRetryConfig, LPItemType, LPUserType, LPHierarchyItem, LPItem, LPAncestor, LPWorkspace, LPMember, LPCostCode, LPSyncResult, LPTimesheetEntry, LPTaskResolution, LPTimesheetOptions, LPUpsertOptions, LPAssignment, LPFindItemsOptions, LPTreeNode, LPWorkspaceTree, } from './types.js';
|
|
33
|
+
export type { LPConfig, LPCacheConfig, LPRetryConfig, LPItemType, LPUserType, LPHierarchyItem, LPItem, LPAncestor, LPWorkspace, LPMember, LPCostCode, LPSyncResult, LPTimesheetEntry, LPTaskResolution, LPTimesheetOptions, LPUpsertOptions, LPAssignment, LPItemRef, LPNormalizedAssignment, LPMemberAssignments, LPAssignmentsResult, LPFindItemsOptions, LPTreeNode, LPWorkspaceTree, } from './types.js';
|
|
34
34
|
export type { AccessTier } from './types.js';
|
|
35
35
|
export { METHOD_TIERS, ENTITIES } from './types.js';
|
|
36
36
|
export { ok, err, getErrorMessage, normalizeEnum, TTLCache, MemoryCacheStore, LayeredCache } from '@markwharton/api-core';
|
package/dist/types.d.ts
CHANGED
|
@@ -283,6 +283,83 @@ export interface LPAssignment extends LPItem {
|
|
|
283
283
|
/** Formatted hierarchy path like "Project A › Subfolder B" (undefined if not requested) */
|
|
284
284
|
hierarchyPath?: string;
|
|
285
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Item reference in the shared items lookup.
|
|
288
|
+
* Extends LPAncestor with parentId for ancestor chain reconstruction.
|
|
289
|
+
*/
|
|
290
|
+
export interface LPItemRef extends LPAncestor {
|
|
291
|
+
parentId?: number;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Assignment in the normalized result.
|
|
295
|
+
*
|
|
296
|
+
* Same fields as LPAssignment minus ancestors and customFieldValues.
|
|
297
|
+
* Ancestors are reconstructable from the items lookup via parentId chain.
|
|
298
|
+
* Custom field values are referenced by index into the shared customFieldValues array.
|
|
299
|
+
*/
|
|
300
|
+
export interface LPNormalizedAssignment {
|
|
301
|
+
id: number;
|
|
302
|
+
name: string | null;
|
|
303
|
+
itemType: LPItemType;
|
|
304
|
+
parentId?: number;
|
|
305
|
+
costCodeId?: number;
|
|
306
|
+
userId?: number;
|
|
307
|
+
expectedStart?: string;
|
|
308
|
+
expectedFinish?: string;
|
|
309
|
+
latestFinish?: string;
|
|
310
|
+
late?: boolean;
|
|
311
|
+
targetStart?: string;
|
|
312
|
+
targetFinish?: string;
|
|
313
|
+
targetFinishType?: string;
|
|
314
|
+
inheritedTargetStartDate?: string;
|
|
315
|
+
inheritedTargetFinishDate?: string;
|
|
316
|
+
scheduleDirective?: string;
|
|
317
|
+
doneDate?: string;
|
|
318
|
+
lowEffort?: number;
|
|
319
|
+
highEffort?: number;
|
|
320
|
+
loggedHoursRollup?: number;
|
|
321
|
+
lowRemainingHoursRollup?: number;
|
|
322
|
+
highRemainingHoursRollup?: number;
|
|
323
|
+
taskStatusId?: number;
|
|
324
|
+
packageStatus?: string;
|
|
325
|
+
folderStatus?: string;
|
|
326
|
+
globalPriority?: string[];
|
|
327
|
+
color?: string;
|
|
328
|
+
workType?: string;
|
|
329
|
+
description?: string;
|
|
330
|
+
createdAt?: string;
|
|
331
|
+
updatedAt?: string;
|
|
332
|
+
clippedHours?: number;
|
|
333
|
+
workLimitHours?: number;
|
|
334
|
+
workLimitRisk?: boolean;
|
|
335
|
+
taskName?: string | null;
|
|
336
|
+
projectId?: number;
|
|
337
|
+
projectName?: string | null;
|
|
338
|
+
hierarchyPath?: string;
|
|
339
|
+
/** Index into the top-level customFieldValues array. Undefined when no custom field values. */
|
|
340
|
+
customFieldValuesIndex?: number;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* One member's assignments in the normalized result
|
|
344
|
+
*/
|
|
345
|
+
export interface LPMemberAssignments {
|
|
346
|
+
memberId: number;
|
|
347
|
+
assignments: LPNormalizedAssignment[];
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Normalized assignments result with shared lookup tables.
|
|
351
|
+
* Deduplicates ancestor items and custom field values to reduce payload size.
|
|
352
|
+
*/
|
|
353
|
+
export interface LPAssignmentsResult {
|
|
354
|
+
/** Assignments grouped by member. One entry when memberId specified, all members when omitted. */
|
|
355
|
+
members: LPMemberAssignments[];
|
|
356
|
+
/** Shared items lookup — walk parentId chains to reconstruct ancestor paths */
|
|
357
|
+
items: Record<number, LPItemRef>;
|
|
358
|
+
/** Deduplicated custom field value sets — indexed by assignment's customFieldValuesIndex */
|
|
359
|
+
customFieldValues: Record<string, unknown>[];
|
|
360
|
+
/** Total items in the workspace tree snapshot */
|
|
361
|
+
treeItemCount: number;
|
|
362
|
+
}
|
|
286
363
|
/**
|
|
287
364
|
* Options for querying items with LP API filters
|
|
288
365
|
*
|