npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

dune-sdk-generator

v1.3.0

Published

Generate strongly-typed TypeScript SDKs from CDF Data Models

Readme

Dune SDK Generator

Generate strongly-typed TypeScript SDKs that unify native CDF APIs and custom Data Modeling types with automatic relationship discovery.

Quick Start

Interactive Mode

CDF_PROJECT="lervik-industries" CDF_TOKEN=$(npx dune-key) npx dune-sdk-generator generate

This launches an interactive UI to browse and select views for SDK generation.

# Specify output location and name
npx dune-sdk-generator generate --output ./sdk --name equipment-sdk

# Regenerate from saved config
npx dune-sdk-generator generate --config dune.config.json

Non-Interactive Mode (Agent-Friendly)

# 1. Search for views
npx dune-sdk-generator search "canvas" --limit 10 > views.json

# 2. Generate SDK non-interactively
npx dune-sdk-generator generate \
  --views views.json \
  --name canvas-sdk \
  --output ./sdk \
  --non-interactive \
  --format json

Environment Variables

| Variable | Required | |----------|----------| | CDF_PROJECT | ✅ | | CDF_TOKEN | ✅ | | CDF_CLUSTER | Optional (default: api) |

Features

🎯 Unified SDK Interface

The generator produces a unified SDK that combines:

  • Native CDF APIs with narrower, InstanceId-focused interfaces (timeseries, files, datapoints, events, sequences, annotations, labels)
  • Custom Data Modeling types discovered via introspection (Canvas, Equipment, etc.)

All accessible from a single entry point:

const sdk = initializeSDK(client);

// Native APIs with narrower interfaces
sdk.timeseries.create([{ space, externalId, name, unit }]);
sdk.files.upload(id, metadata, content);
sdk.datapoints.insert([{ id, datapoints }]);

// Custom DM types
sdk.canvas.create({ space, externalId, properties });
sdk.equipment.list({ filter });

Key Benefits:

  • Consistent patterns: All APIs use InstanceId instead of mixed id/externalId
  • Type safety: Full TypeScript support across native and custom types
  • Unified workflows: Seamlessly combine native APIs with Data Modeling
  • Focused interfaces: Streamlined API surface removes unused parameters

🤖 Agent-Friendly CLI

The CLI is designed for both interactive use and programmatic/agentic workflows:

  • search - Search for views by keyword with JSON output
  • introspect - Get detailed view definitions
  • generate - Generate SDKs interactively or non-interactively
  • --format json - Machine-readable output for parsing
  • --non-interactive - Skip all prompts for CI/CD and agent contexts

See CLI Reference for details.

🎯 Type-Safe CRUD Operations

Generated SDKs provide fully typed methods for:

  • create() - Create new instances
  • get() - Retrieve by ID
  • update() - Update existing instances
  • delete() - Delete instances
  • list() - List with pagination and filtering
  • query() - Advanced queries with custom filters

🔗 Reverse Relationships

The SDK generator automatically discovers reverse relationships in your data model.

What are Reverse Relationships?

In data modeling, you often have one-way references:

  • CanvasAnnotation has a property canvas: InstanceId pointing to Canvas
  • Canvas doesn't explicitly know about CanvasAnnotation
  • But semantically, a Canvas "has many" CanvasAnnotations

The SDK generator discovers these implicit relationships and generates helper methods:

// Without reverse relationships (manual query)
const annotations = await client.canvasAnnotations.query({
  filter: {
    equals: {
      property: CanvasAnnotationSDK.PROPERTY_PATHS.canvas,
      value: { space: 'mySpace', externalId: 'canvas-1' }
    }
  }
});

// With reverse relationships (generated helper)
const annotations = await client.canvases.getAnnotations(
  { space: 'mySpace', externalId: 'canvas-1' }
);

Interactive Configuration

When you generate an SDK, the CLI automatically discovers and prompts you to configure reverse relationships:

npx dune-sdk-generator generate

# After view selection and introspection...
🔗 Discovered 3 reverse relationship(s):

   Canvas:
      • getAnnotations() → CanvasAnnotation[]
        from CanvasAnnotation.canvas
      • getComments() → CanvasComment[]
        from CanvasComment.canvas

   Equipment:
      • getMaintenanceRecords() → MaintenanceRecord[]
        from MaintenanceRecord.equipment

? Enable reverse relationships in the generated SDK? (Y/n)
? Review and customize relationship names? (y/N)

Interactive Customization:

If you choose to review/customize (or if conflicts are detected):

Canvas.getAnnotations()
   From: CanvasAnnotation.canvas
   Returns: CanvasAnnotation[]

? Configure this relationship:
  ❯ Keep default (getAnnotations)
    Customize method name
    Skip this relationship

# If you choose "Customize method name":
? Method name: getCanvasAnnotations

Conflict Detection:

The CLI automatically detects naming conflicts:

⚠️  Naming conflicts detected:

   Canvas.getAnnotations
      Multiple relationships would generate the same method name

? Review and customize relationship names? (Y/n)  # Required for conflicts

Configuration is Saved: Your choices are automatically saved to dune.config.json for regeneration.

Manual Configuration (Advanced)

You can also edit dune.config.json directly:

{
  "reverseRelationships": {
    "Canvas": {
      "annotations": {
        "from": "CanvasAnnotation.canvas",
        "methodName": "getAnnotations"
      }
    }
  }
}

When regenerating with --config, your existing relationship configuration is preserved.

Generated Methods

For each reverse relationship, the SDK generates:

/**
 * Get all CanvasAnnotation that reference this Canvas
 * 
 * This is a reverse relationship - CanvasAnnotation has a property 'canvas'
 * that references Canvas, but Canvas doesn't explicitly define this relationship.
 * 
 * @param id The Canvas instance to find related CanvasAnnotation for
 * @param options Query options (limit, additional filters, cursor)
 * @returns Array of CanvasAnnotation instances referencing this Canvas
 * 
 * @performance This performs a filtered query on CanvasAnnotation
 */
async getAnnotations(
  id: InstanceId,
  options?: {
    limit?: number;
    additionalFilter?: any;
    cursor?: string;
  }
): Promise<CanvasAnnotation[]>

Advanced Usage

Combine reverse relationships with additional filters:

// Get only annotations created in the last week
const recentAnnotations = await client.canvases.getAnnotations(
  canvasId,
  {
    limit: 50,
    additionalFilter: {
      range: {
        property: ['node', 'createdTime'],
        gte: Date.now() - 7 * 24 * 60 * 60 * 1000
      }
    }
  }
);

📦 Dependency Resolution

The generator automatically:

  • Discovers parent views (via implements)
  • Generates type definitions for dependencies
  • Resolves transitive dependencies

🔄 Regeneration

Save your configuration for easy regeneration:

# First generation saves config
npx dune-sdk-generator generate

# Later regeneration
npx dune-sdk-generator generate --config dune.config.json

CLI Reference

search Command

Search for views by keyword and output results in JSON format compatible with --views.

dune-sdk-generator search <query> [options]

Arguments:

  • <query> - Search query string (single query per command)

Options:

  • --limit <number> - Maximum number of results (default: 1000)

Output: JSON array of view references

[
  {
    "space": "cdf_industrial_canvas",
    "externalId": "Canvas",
    "version": "v1"
  }
]

Examples:

# Search for canvas-related views
dune-sdk-generator search "canvas" > canvas-views.json

# Search with custom limit
dune-sdk-generator search "equipment" --limit 50

# Multiple searches (run separately)
dune-sdk-generator search "annotation" > annotations.json
dune-sdk-generator search "comment" > comments.json

introspect Command

Get detailed view definitions including properties, constraints, and relationships.

dune-sdk-generator introspect <references...>

Arguments:

  • <references...> - One or more view references in format: space/externalId/version

Output: JSON array of complete view definitions

Examples:

# Introspect single view
dune-sdk-generator introspect cdf_industrial_canvas/Canvas/v1

# Introspect multiple views
dune-sdk-generator introspect \
  cdf_industrial_canvas/Canvas/v1 \
  cdf_industrial_canvas/CanvasAnnotation/v1

generate Command

Generate SDK with interactive or non-interactive view selection.

dune-sdk-generator generate [options]

Options:

  • --views <path|json> - Views to generate SDK for (file path or inline JSON array)
  • --output <path> - Output directory (default: ./sdk)
  • --name <name> - SDK name for generated file (default: generated-sdk)
  • --reverse-relationships <mode> - Reverse relationship mode: auto, none, or config (default: auto)
  • --non-interactive, -y - Skip all prompts (use defaults or fail)
  • --format <format> - Output format: text or json (default: text)
  • --config <path> - Regenerate from existing config file

Native API Configuration:

During interactive generation, you'll be prompted:

? Include native CDF API wrappers (timeseries, files, datapoints, etc.)? (Y/n)

By default, all native APIs are included. You can configure which APIs to include in dune.config.json:

{
  "includeNativeAPIs": true,
  "nativeAPIs": {
    "timeseries": true,
    "files": true,
    "datapoints": true,
    "events": true,
    "sequences": true,
    "annotations": true,
    "labels": true
  }
}

Modes:

  1. Interactive Mode (default): Browse and select views with UI
  2. Non-Interactive Mode: Provide views via --views flag
  3. Regeneration Mode: Use existing config with --config

Examples:

# Interactive mode
dune-sdk-generator generate

# Non-interactive with views from file
dune-sdk-generator generate \
  --views views.json \
  --name my-sdk \
  --output ./sdk \
  --non-interactive

# Non-interactive with inline JSON
dune-sdk-generator generate \
  --views '[{"space":"x","externalId":"y","version":"v1"}]' \
  --non-interactive \
  --format json

# Regenerate from config
dune-sdk-generator generate --config dune.config.json

# Non-interactive without reverse relationships
dune-sdk-generator generate \
  --views views.json \
  --reverse-relationships none \
  --non-interactive

JSON Output Format (when --format json):

{
  "success": true,
  "sdkName": "my-sdk",
  "outputDirectory": "./sdk",
  "files": [
    "./sdk/my-sdk.ts",
    "./sdk/my-sdk.test.ts"
  ],
  "configPath": "./dune.config.json",
  "stats": {
    "sdkViews": 5,
    "typeOnlyViews": 3,
    "reverseRelationships": 8
  }
}

Generated SDK Structure

The generated SDK provides a unified interface combining both native CDF APIs and custom Data Modeling types:

// Initialize SDK
import { CogniteClient } from '@cognite/sdk';
import { initializeSDK } from './sdk/my-sdk';

const client = new CogniteClient({ ... });
const sdk = initializeSDK(client);

// ============================================================================
// Native CDF APIs (Focused Interfaces)
// ============================================================================

// Time Series - InstanceId-based interface
const timeseries = await sdk.timeseries.create([{
  space: 'mySpace',
  externalId: 'temp-sensor-1',
  name: 'Temperature Sensor',
  unit: 'C',
  isStep: false
}]);

// Data Points - Insert and retrieve
await sdk.datapoints.insert([{
  id: { space: 'mySpace', externalId: 'temp-sensor-1' },
  datapoints: [
    { timestamp: Date.now(), value: 23.5 },
    { timestamp: Date.now() + 60000, value: 24.1 }
  ]
}]);

const datapoints = await sdk.datapoints.retrieve({
  items: [{ id: { space: 'mySpace', externalId: 'temp-sensor-1' } }],
  start: Date.now() - 3600000,
  end: Date.now()
});

// Files - Upload and download
await sdk.files.upload(
  { space: 'mySpace', externalId: 'manual-1' },
  { name: 'equipment-manual.pdf', mimeType: 'application/pdf' },
  fileBuffer
);

const fileData = await sdk.files.download({ space: 'mySpace', externalId: 'manual-1' });

// Events - Create with instance linkage
await sdk.events.create([{
  type: 'maintenance',
  description: 'Routine inspection',
  startTime: new Date(),
  linkedInstance: { space: 'mySpace', externalId: 'equipment-1' }
}]);

// Find events for an instance
const events = await sdk.events.findByInstance(
  { space: 'mySpace', externalId: 'equipment-1' }
);

// ============================================================================
// Custom Data Modeling Types
// ============================================================================

// Create canvas instance
const canvas = await sdk.canvas.create({
  space: 'mySpace',
  externalId: 'canvas-1',
  properties: {
    name: 'My Canvas',
    width: 1920,
    height: 1080
  }
});

// Use reverse relationships
const annotations = await sdk.canvas.getAnnotations(
  { space: canvas.space, externalId: canvas.externalId }
);

// Query with filters
const results = await sdk.canvas.query({
  filter: {
    equals: {
      property: ['mySpace', 'Canvas/v1', 'name'],
      value: 'My Canvas'
    }
  },
  limit: 100
});

// ============================================================================
// Combined Workflows
// ============================================================================

// Create equipment with time series and files
const equipment = await sdk.equipment.create({
  space: 'industrial',
  externalId: 'pump-001',
  properties: {
    name: 'Main Pump',
    location: 'Building A'
  }
});

// Create associated time series
await sdk.timeseries.create([{
  space: 'industrial',
  externalId: 'pump-001-pressure',
  name: 'Pump 001 Pressure',
  unit: 'bar'
}]);

// Upload equipment manual
await sdk.files.upload(
  { space: 'industrial', externalId: 'pump-001-manual' },
  { name: 'pump-manual.pdf' },
  manualBuffer
);

// Log maintenance event
await sdk.events.create([{
  type: 'maintenance',
  description: 'Pressure sensor calibration',
  linkedInstance: { space: 'industrial', externalId: 'pump-001' }
}]);

Agentic Usage Guide

This section demonstrates how an AI agent can use the CLI to help users generate SDKs through a conversational workflow.

End-to-End Agentic Workflow

Here's a complete example of how an agent would interact with a user to generate an SDK:

  1. Understand Requirements - Ask user for keywords
  2. Search - Find matching views
  3. Introspect - Analyze view structure and relationships
  4. Present Options - Show recommendations based on analysis
  5. Prepare - Create filtered view list
  6. Configure - Get SDK preferences
  7. Generate - Create SDK non-interactively
  8. Report - Parse and display results

Step 1: Understand User Requirements

Agent: "What data models would you like to generate an SDK for? Please provide some keywords that describe the views you need (e.g., 'canvas', 'equipment', 'work orders')."

User: "I need views related to industrial canvases and annotations"

Agent: "Got it! Let me search for views matching those keywords..."

Step 2: Search for Views

# Agent executes: Search for "canvas" views
dune-sdk-generator search "canvas" --limit 50 > canvas-results.json

# Agent executes: Search for "annotation" views  
dune-sdk-generator search "annotation" --limit 50 > annotation-results.json

Step 3: Introspect Views to Understand Structure

# Agent parses search results and introspects top candidates
dune-sdk-generator introspect \
  cdf_industrial_canvas/Canvas/v1 \
  cdf_industrial_canvas/CanvasConfig/v1 \
  cdf_apps_shared/Canvas/v1 \
  cdf_industrial_canvas/CanvasAnnotation/v1 \
  cdf_apps_shared/Annotation/v1 > view-details.json
Agent analyzes the introspection results:
- Canvas (cdf_industrial_canvas): 15 properties, implements CogniteDescribableNode
  - Has relationships to CanvasAnnotation, CanvasComment
  - Properties: name, width, height, data, etc.
  
- CanvasAnnotation (cdf_industrial_canvas): 8 properties
  - References Canvas via 'canvas' property (direct relation)
  - Properties: text, position, color, etc.
  
- CanvasConfig (cdf_industrial_canvas): 5 properties
  - Configuration for canvas display settings
  
- Canvas (cdf_apps_shared): Similar to cdf_industrial_canvas/Canvas
  - Likely a duplicate/different version
  
- Annotation (cdf_apps_shared): Generic annotation
  - May not be specific to Canvas

Step 4: Present Analyzed Results to User

Agent: "I found the following views that match your criteria. After analyzing their structure, here are my recommendations:

✅ Recommended (tightly related to industrial canvases):
  • cdf_industrial_canvas/Canvas/v1
    - Main canvas view with 15 properties
    - Core entity for canvas operations
  
  • cdf_industrial_canvas/CanvasAnnotation/v1
    - Annotations linked to Canvas (8 properties)
    - Has direct relationship to Canvas
  
  • cdf_industrial_canvas/CanvasConfig/v1
    - Canvas display configuration (5 properties)
    - Likely needed for Canvas functionality

⚠️  Alternative options (may be duplicates):
  • cdf_apps_shared/Canvas/v1
    - Similar to the industrial canvas version
    - Consider if you need both
  
  • cdf_apps_shared/Annotation/v1
    - Generic annotation, not canvas-specific

My recommendation: Start with the three cdf_industrial_canvas views. They form a cohesive set for canvas and annotation management.

Would you like to:
  a) Generate SDK with my recommended views
  b) Include the cdf_apps_shared views as well
  c) Let me search for additional related views
  
Please choose an option."

User: "Option a, that looks perfect"

Agent: "Excellent! I'll generate an SDK with these three cohesive views:
  • Canvas (main entity)
  • CanvasAnnotation (linked annotations)
  • CanvasConfig (configuration)

This will include automatic reverse relationships, so you'll be able to:
  - Get all annotations for a canvas: canvas.getAnnotations()
  - Standard CRUD operations on all three types
  - Type-safe access to all properties"

Step 5: Prepare View List

# Agent creates a filtered views.json file
cat > views.json << 'EOF'
[
  {
    "space": "cdf_industrial_canvas",
    "externalId": "Canvas",
    "version": "v1"
  },
  {
    "space": "cdf_industrial_canvas",
    "externalId": "CanvasConfig",
    "version": "v1"
  },
  {
    "space": "cdf_industrial_canvas",
    "externalId": "CanvasAnnotation",
    "version": "v1"
  }
]
EOF

Step 6: Ask for Configuration Preferences

Agent: "Great! Now I need a few configuration details:

1. What should I name the SDK? (default: generated-sdk)
2. Where should I output the files? (default: ./sdk)
3. Should I include reverse relationships? (recommended: yes)

Please provide your preferences or type 'use defaults'."

User: "Name it canvas-sdk, output to ./src/sdk, and yes to reverse relationships"

Step 7: Generate SDK Non-Interactively

# Agent executes the generation
dune-sdk-generator generate \
  --views views.json \
  --name canvas-sdk \
  --output ./src/sdk \
  --reverse-relationships auto \
  --non-interactive \
  --format json > generation-result.json

Step 8: Report Results

# Agent parses the JSON output
cat generation-result.json
{
  "success": true,
  "sdkName": "canvas-sdk",
  "outputDirectory": "./src/sdk",
  "files": [
    "./src/sdk/canvas-sdk.ts",
    "./src/sdk/canvas-sdk.test.ts"
  ],
  "configPath": "./dune.config.json",
  "stats": {
    "sdkViews": 3,
    "typeOnlyViews": 2,
    "reverseRelationships": 5
  }
}
Agent: "✅ SDK generated successfully!

Generated files:
  • ./src/sdk/canvas-sdk.ts (main SDK)
  • ./src/sdk/canvas-sdk.test.ts (test suite)
  • ./dune.config.json (configuration for regeneration)

SDK Stats:
  • 3 main views with full CRUD operations
  • 2 type-only dependency views
  • 5 reverse relationships discovered

You can now import and use your SDK:
  import { initializeSDK } from './src/sdk/canvas-sdk';
  
To regenerate later with the same configuration:
  dune-sdk-generator generate --config dune.config.json"

Agent Implementation Example

Here's how to implement the agentic workflow in code:

// Example agent implementation
async function generateSDKWithAgent(userRequest: string) {
  // 1. Extract keywords from user request
  const keywords = extractKeywords(userRequest); // e.g., ["canvas", "annotation"]
  
  // 2. Search for each keyword
  const allViews = [];
  for (const keyword of keywords) {
    const { stdout } = await exec(
      `dune-sdk-generator search "${keyword}" --limit 50`
    );
    const views = JSON.parse(stdout);
    allViews.push(...views);
  }
  
  // 3. Remove duplicates
  const uniqueViews = deduplicateViews(allViews);
  
  // 4. Introspect views to understand their structure
  const viewRefs = uniqueViews.map(v => `${v.space}/${v.externalId}/${v.version}`);
  const { stdout: introspectData } = await exec(
    `dune-sdk-generator introspect ${viewRefs.join(' ')}`
  );
  const viewDetails = JSON.parse(introspectData);
  
  // 5. Analyze views to make recommendations
  const analysis = analyzeViews(viewDetails);
  // - Check for relationships between views
  // - Count properties
  // - Identify core vs auxiliary views
  // - Detect duplicates across spaces
  
  // 6. Present recommendations to user
  const recommendations = await presentRecommendations(analysis, uniqueViews);
  const selectedViews = await askUserToConfirm(recommendations);
  
  // 7. Write selected views to file
  await writeFile('views.json', JSON.stringify(selectedViews, null, 2));
  
  // 8. Get configuration preferences
  const config = await askUserForConfig();
  
  // 9. Generate SDK
  const { stdout } = await exec(
    `dune-sdk-generator generate \
      --views views.json \
      --name ${config.name} \
      --output ${config.output} \
      --reverse-relationships auto \
      --non-interactive \
      --format json`
  );
  
  // 10. Parse and report results
  const result = JSON.parse(stdout);
  return result;
}

// Helper function to analyze view relationships
function analyzeViews(viewDetails: any[]): ViewAnalysis {
  const relationships = new Map();
  
  for (const view of viewDetails) {
    // Check for direct relations pointing to other views
    for (const [propName, prop] of Object.entries(view.properties || {})) {
      if (prop.type?.type === 'direct') {
        const target = findViewByContainer(viewDetails, prop.type.source);
        if (target) {
          relationships.set(
            `${view.externalId}->${target.externalId}`,
            { source: view, target, property: propName }
          );
        }
      }
    }
  }
  
  return {
    views: viewDetails,
    relationships: Array.from(relationships.values()),
    clusters: clusterRelatedViews(viewDetails, relationships),
  };
}

Quick Scripts for Agents

Simple view search with introspection:

#!/bin/bash
# search-and-select.sh

KEYWORD=$1
echo "Searching for views matching: $KEYWORD"

# Search
dune-sdk-generator search "$KEYWORD" --limit 20 > results.json

# Show results
echo "Found views:"
jq -r '.[] | "  • \(.space)/\(.externalId)/\(.version)"' results.json

# Introspect top 5 views to understand structure
echo ""
echo "Analyzing top 5 views..."
VIEW_REFS=$(jq -r 'limit(5; .[]) | "\(.space)/\(.externalId)/\(.version)"' results.json | tr '\n' ' ')
dune-sdk-generator introspect $VIEW_REFS > introspect-results.json

# Show analysis
echo ""
echo "View details:"
jq -r '.[] | "  \(.externalId): \(.properties | length) properties"' introspect-results.json

echo ""
echo "Full results saved to:"
echo "  - results.json (search results)"
echo "  - introspect-results.json (detailed view info)"
echo ""
echo "To generate SDK: dune-sdk-generator generate --views results.json --non-interactive"

Batch SDK generation:

#!/bin/bash
# batch-generate.sh

for config in ./configs/*.json; do
  sdk_name=$(basename "$config" .json)
  echo "Generating SDK: $sdk_name"
  
  dune-sdk-generator generate \
    --views "$config" \
    --name "$sdk_name" \
    --output "./sdks/$sdk_name" \
    --non-interactive \
    --format json > "./results/${sdk_name}-result.json"
    
  echo "✓ $sdk_name complete"
done

CI/CD Integration

Using in GitHub Actions:

# .github/workflows/generate-sdk.yml
name: Generate SDK

on:
  push:
    paths:
      - 'config/views.json'

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Generate SDK
        run: |
          npx dune-sdk-generator generate \
            --views ./config/views.json \
            --name production-sdk \
            --output ./src/sdk \
            --non-interactive \
            --format json > result.json
        env:
          CDF_PROJECT: ${{ secrets.CDF_PROJECT }}
          CDF_TOKEN: ${{ secrets.CDF_TOKEN }}
      
      - name: Check result
        run: |
          if jq -e '.success == true' result.json > /dev/null; then
            echo "✅ SDK generated successfully"
            jq '.stats' result.json
          else
            echo "❌ SDK generation failed"
            jq '.error' result.json
            exit 1
          fi
      
      - name: Commit generated SDK
        run: |
          git config user.name "SDK Generator Bot"
          git config user.email "[email protected]"
          git add src/sdk/
          git commit -m "chore: regenerate SDK"
          git push

Best Practices

Reverse Relationships

  1. Start with Auto-Discovery: Enable autoDiscoverReverseRelationships: true to see all possible relationships
  2. Refine Manually: Switch to manual configuration to control which relationships are exposed
  3. Name Thoughtfully: Use descriptive method names that reflect the business domain
  4. Document Performance: Reverse relationships perform queries - be mindful of limits and pagination

Conflict Resolution

The CLI automatically detects naming conflicts:

⚠️  Naming conflicts detected:

   Canvas.getItems
      Multiple relationships would generate the same method name

? Review and customize relationship names? (Y/n)  # Defaults to Yes

When conflicts are detected:

  • You'll be prompted to customize (required to proceed)
  • The CLI suggests the conflicting relationships
  • You provide unique names for each

Performance

  • Use limit parameter to control result set size
  • Leverage cursor for pagination
  • Add additionalFilter to narrow results
  • Consider caching frequently accessed relationships

Development

Reference SDK Source

For development, you can clone the Cognite SDK source for reference:

mkdir -p reference
git clone https://github.com/cognitedata/cognite-sdk-js.git reference/cognite-sdk

This directory is gitignored and read-only (via Cursor rules).

License

MIT