---
title: "Advanced Examples"
description: "Advanced patterns and complex use cases with the TraceRTM JavaScript SDK"
---

# Advanced Examples

Complex patterns and advanced use cases for the TraceRTM JavaScript SDK.

## Concurrent Operations

### Parallel Item Creation

```typescript
async function createItemsInParallel(
  projectId: string,
  items: Array<{ title: string; type: ItemType }>
) {
  const promises = items.map((item) =>
    client.items.create({
      projectId,
      type: item.type,
      title: item.title,
    })
  );

  return Promise.all(promises);
}

// Usage
const created = await createItemsInParallel("proj_123", [
  { title: "Req 1", type: "requirement" },
  { title: "Req 2", type: "requirement" },
  { title: "Test 1", type: "test_case" },
]);
```

### Controlled Concurrency

```typescript
async function processWithConcurrencyLimit<T, R>(
  items: T[],
  processor: (item: T) => Promise<R>,
  maxConcurrent: number = 5
): Promise<R[]> {
  const results: R[] = [];
  const executing: Promise<void>[] = [];

  for (const item of items) {
    const promise = processor(item).then((result) => {
      results.push(result);
    });

    executing.push(promise);

    if (executing.length >= maxConcurrent) {
      await Promise.race(executing);
      // Remove completed promises
      const completed = executing.filter((p) => {
        const status = Promise.race([p, Promise.resolve("pending")]);
        return status !== "pending";
      });
      executing.length = 0;
      executing.push(...completed);
    }
  }

  await Promise.all(executing);
  return results;
}

// Usage
const itemIds = ["item_1", "item_2", "item_3", "item_4", "item_5"];
const items = await processWithConcurrencyLimit(
  itemIds,
  (id) => client.items.get(id),
  3 // Max 3 concurrent requests
);
```

---

## Data Migration

### Migrate Project Between Instances

```typescript
async function migrateProject(
  sourceClient: TraceRTMClient,
  targetClient: TraceRTMClient,
  projectId: string
) {
  // Get source project
  const sourceProject = await sourceClient.projects.get(projectId);

  // Create in target
  const targetProject = await targetClient.projects.create({
    name: sourceProject.name,
    key: sourceProject.key,
    description: sourceProject.description,
  });

  // Map old IDs to new IDs
  const idMap = new Map<string, string>();

  // Migrate items
  let offset = 0;
  const limit = 100;

  while (true) {
    const items = await sourceClient.items.list({
      projectId,
      limit,
      offset,
    });

    for (const item of items.data) {
      const newItem = await targetClient.items.create({
        projectId: targetProject.id,
        type: item.type,
        title: item.title,
        description: item.description,
        priority: item.priority,
        status: item.status,
        tags: item.tags,
      });

      idMap.set(item.id, newItem.id);
    }

    if (!items.hasMore) break;
    offset += limit;
  }

  // Migrate links
  const links = await sourceClient.links.list({ projectId });

  for (const link of links.data) {
    const newSourceId = idMap.get(link.sourceId);
    const newTargetId = idMap.get(link.targetId);

    if (newSourceId && newTargetId) {
      await targetClient.links.create({
        sourceId: newSourceId,
        targetId: newTargetId,
        type: link.type,
        description: link.description,
      });
    }
  }

  return { targetProject, itemsMigrated: idMap.size };
}
```

### Import from CSV

```typescript
import { parse } from "csv-parse/sync";
import fs from "fs";

interface CsvRequirement {
  Title: string;
  Description: string;
  Priority: string;
  Tags: string;
}

async function importFromCsv(projectId: string, filePath: string) {
  const content = fs.readFileSync(filePath, "utf-8");
  const records: CsvRequirement[] = parse(content, {
    columns: true,
    skip_empty_lines: true,
  });

  const items = records.map((record) => ({
    projectId,
    type: "requirement" as const,
    title: record.Title,
    description: record.Description,
    priority: record.Priority.toLowerCase() as Priority,
    tags: record.Tags.split(",").map((t) => t.trim()),
  }));

  // Bulk create in batches
  const batchSize = 50;
  const created: Item[] = [];

  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    const result = await client.items.bulkCreate(batch);
    created.push(...result);
  }

  return created;
}
```

---

## Workflow Automation

### Auto-Link on Creation

```typescript
async function createRequirementWithAutoLink(
  projectId: string,
  title: string,
  description: string
) {
  // Create requirement
  const req = await client.items.create({
    projectId,
    type: "requirement",
    title,
    description,
    priority: "high",
  });

  // Find similar existing test cases
  const tests = await client.search.items({
    query: title,
    projectIds: [projectId],
    types: ["test_case"],
    limit: 5,
  });

  // Auto-link high-confidence matches
  for (const hit of tests.items) {
    if (hit.score > 0.7) {
      await client.links.create({
        sourceId: req.id,
        targetId: hit.item.id,
        type: "verified_by",
        description: `Auto-linked (score: ${hit.score.toFixed(2)})`,
      });
    }
  }

  return req;
}
```

### Status Transition Workflow

```typescript
const WORKFLOW_TRANSITIONS: Record<string, string[]> = {
  draft: ["in_review"],
  in_review: ["approved", "rejected"],
  approved: ["implemented"],
  rejected: ["draft"],
  implemented: ["verified"],
  verified: ["released"],
};

async function transitionItem(itemId: string, newStatus: string) {
  const item = await client.items.get(itemId);
  const allowedTransitions = WORKFLOW_TRANSITIONS[item.status] || [];

  if (!allowedTransitions.includes(newStatus)) {
    throw new Error(
      `Cannot transition from ${item.status} to ${newStatus}. ` +
        `Allowed: ${allowedTransitions.join(", ")}`
    );
  }

  return client.items.update(itemId, { status: newStatus });
}
```

### Approval Workflow

```typescript
interface ApprovalResult {
  item: Item;
  approved: boolean;
  approver: string;
  comments?: string;
}

async function requestApproval(
  itemId: string,
  approverIds: string[]
): Promise<void> {
  await client.items.update(itemId, {
    status: "pending_approval",
    fields: {
      approvers: approverIds,
      approvalRequested: new Date().toISOString(),
    },
  });
}

async function approveItem(
  itemId: string,
  approverId: string,
  comments?: string
): Promise<Item> {
  const item = await client.items.get(itemId);

  const approvers = (item.fields.approvers as string[]) || [];
  if (!approvers.includes(approverId)) {
    throw new Error("User is not an approver for this item");
  }

  const existingApprovals = (item.fields.approvals as ApprovalResult[]) || [];
  existingApprovals.push({
    item,
    approved: true,
    approver: approverId,
    comments,
  });

  // Check if all approvers have approved
  const allApproved = approvers.every((id) =>
    existingApprovals.some((a) => a.approver === id && a.approved)
  );

  return client.items.update(itemId, {
    status: allApproved ? "approved" : "pending_approval",
    fields: {
      ...item.fields,
      approvals: existingApprovals,
    },
  });
}
```

---

## Reporting & Analytics

### Generate Release Notes

```typescript
async function generateReleaseNotes(
  projectId: string,
  releaseTag: string
): Promise<string> {
  const items = await client.items.list({
    projectId,
    tags: [releaseTag],
    statusCategory: "done",
  });

  const byType = new Map<ItemType, Item[]>();
  for (const item of items.data) {
    const list = byType.get(item.type) || [];
    list.push(item);
    byType.set(item.type, list);
  }

  let notes = `# Release Notes - ${releaseTag}\n\n`;

  const typeLabels: Record<ItemType, string> = {
    requirement: "New Features",
    user_story: "User Stories",
    bug: "Bug Fixes",
    task: "Tasks",
    test_case: "Tests",
    risk: "Risk Items",
    decision: "Decisions",
    epic: "Epics",
    feature: "Features",
  };

  for (const [type, items] of byType) {
    notes += `## ${typeLabels[type] || type}\n\n`;
    for (const item of items) {
      notes += `- ${item.title}\n`;
      if (item.description) {
        notes += `  ${item.description.substring(0, 100)}...\n`;
      }
    }
    notes += "\n";
  }

  return notes;
}
```

### Compliance Report

```typescript
interface ComplianceReport {
  projectId: string;
  generatedAt: string;
  requirementsCoverage: number;
  allRequirementsTracked: boolean;
  allTestsExecuted: boolean;
  issues: string[];
}

async function generateComplianceReport(
  projectId: string
): Promise<ComplianceReport> {
  const issues: string[] = [];

  // Check requirement coverage
  const coverage = await client.reports.coverage({
    projectId,
    sourceType: "requirement",
    targetType: "test_case",
  });

  if (coverage.uncoveredCount > 0) {
    issues.push(
      `${coverage.uncoveredCount} requirements lack test coverage`
    );
  }

  // Check for unapproved requirements
  const unapproved = await client.items.list({
    projectId,
    type: "requirement",
    status: ["draft", "in_review"],
  });

  if (unapproved.total > 0) {
    issues.push(`${unapproved.total} requirements not yet approved`);
  }

  // Check test execution
  const tests = await client.items.list({
    projectId,
    type: "test_case",
  });

  const unexecuted = tests.data.filter((t) => t.status === "not_run");
  if (unexecuted.length > 0) {
    issues.push(`${unexecuted.length} test cases not executed`);
  }

  return {
    projectId,
    generatedAt: new Date().toISOString(),
    requirementsCoverage: coverage.coveragePercent,
    allRequirementsTracked: coverage.uncoveredCount === 0,
    allTestsExecuted: unexecuted.length === 0,
    issues,
  };
}
```

---

## Integration Patterns

### Webhook Handler

```typescript
import express from "express";
import crypto from "crypto";

const app = express();

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

app.post(
  "/webhooks/tracertm",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const signature = req.headers["x-tracertm-signature"] as string;
    const payload = req.body.toString();

    if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET!)) {
      return res.status(401).send("Invalid signature");
    }

    const event = JSON.parse(payload);

    switch (event.event) {
      case "item.created":
        console.log(`New item: ${event.data.title}`);
        break;
      case "item.status_changed":
        console.log(
          `Status changed: ${event.data.oldStatus} -> ${event.data.newStatus}`
        );
        break;
      case "link.created":
        console.log(`New link: ${event.data.sourceId} -> ${event.data.targetId}`);
        break;
    }

    res.status(200).send("OK");
  }
);
```

### Sync with External System

```typescript
interface ExternalItem {
  externalId: string;
  title: string;
  status: string;
}

async function syncFromExternal(
  projectId: string,
  externalItems: ExternalItem[]
) {
  const existing = await client.items.list({
    projectId,
    limit: 1000,
  });

  const existingByExternalId = new Map(
    existing.data
      .filter((item) => item.fields.externalId)
      .map((item) => [item.fields.externalId as string, item])
  );

  const results = { created: 0, updated: 0, unchanged: 0 };

  for (const ext of externalItems) {
    const existing = existingByExternalId.get(ext.externalId);

    if (!existing) {
      // Create new
      await client.items.create({
        projectId,
        type: "requirement",
        title: ext.title,
        status: ext.status,
        fields: { externalId: ext.externalId },
      });
      results.created++;
    } else if (
      existing.title !== ext.title ||
      existing.status !== ext.status
    ) {
      // Update
      await client.items.update(existing.id, {
        title: ext.title,
        status: ext.status,
      });
      results.updated++;
    } else {
      results.unchanged++;
    }
  }

  return results;
}
```

---

## Related Documentation

- [Basic Examples](/docs/api-reference/sdks/javascript/basic-examples) - Simple examples
- [Async/Await](/docs/api-reference/sdks/javascript/async-await) - Async patterns
- [Error Handling](/docs/api-reference/sdks/javascript/error-handling) - Error handling
