Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .copyrightconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ startyear: 2015
# - Dotfiles already skipped automatically
# Enable by removing the leading '# ' from the next line and editing values.
# filesexcluded: third_party/*, docs/generated/*.md, assets/*.png, scripts/temp_*.py, vendor/lib.js
filesexcluded: .github/*, README.md, Jenkinsfile, test-app/*, *.md, docker-compose.yaml, test-complete-app-mlDeploy/*, *.json
filesexcluded: .github/*, README.md, Jenkinsfile, test-app/*, *.md, docker-compose.yaml, test-complete-app-mlDeploy/*, *.json, *.sh
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ or
There are also tests in the `test-complete` folder. The setup for these is more complicated and can
be found in the `Jenkinsfile` file in this repository in the `runE2ETests` function.

## Testing TypeScript support

The 4.1.0 release will add TypeScript support for the client. To try this out locally and manually,
see the `README.md` file in the `./typescript-test-project` directory.

## Generating documentation

After installing the project dependencies, you can build the reference documentation locally from the root
Expand Down
36 changes: 34 additions & 2 deletions marklogic.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,36 @@ declare module 'marklogic' {
apiVersion?: string;
}

/**
* Result object returned by checkConnection method.
*/
export interface ConnectionCheckResult {
/** Whether the connection was successful */
connected: boolean;
/** HTTP status code if connection failed */
httpStatusCode?: number;
/** HTTP status message if connection failed */
httpStatusMessage?: string;
}

/**
* A database client object returned by createDatabaseClient.
* Provides access to document, graph, and query operations.
*/
export interface DatabaseClient {
// Methods will be added as we expand the type definitions
// For now, this is a placeholder to enable basic typing
/**
* Tests if a connection is successful.
* @since 2.1
* @returns A promise that resolves to an object indicating connection status
*/
checkConnection(): Promise<ConnectionCheckResult>;

/**
* Releases the client and destroys the agent.
* Call this method when you're done with the client to free up resources.
* @since 3.0.0
*/
release(): void;
}

/**
Expand All @@ -76,8 +99,17 @@ declare module 'marklogic' {
*/
export function createDatabaseClient(config: DatabaseClientConfig): DatabaseClient;

/**
* Releases a client and destroys its agent.
* This is a standalone function equivalent to calling client.release().
* @since 3.0.0
* @param client - The DatabaseClient to release
*/
export function releaseClient(client: DatabaseClient): void;

const marklogic: {
createDatabaseClient: typeof createDatabaseClient;
releaseClient: typeof releaseClient;
};

export default marklogic;
Expand Down
34 changes: 0 additions & 34 deletions test-typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,6 @@ npm run test:types

This command runs `tsc --noEmit`, which checks for TypeScript errors without generating JavaScript files.

## What Gets Tested

### ✅ Type Constraints
- Valid values for `authType` (basic, digest, application-level, certificate, kerberos, saml, cloud)
- Optional vs required properties
- Union types (string | Buffer for certificates)
- Array types (string[] for multiple certificates)

### ✅ Type Safety
If you uncomment the error examples in the test files, TypeScript will catch:
- Invalid `authType` values
- Incorrect property types
- Missing required properties

## Test Files

### `type-constraints.test.ts`
Tests the `DatabaseClientConfig` interface constraints without importing the module. This works immediately without needing to simulate package installation.

### `basic-types.test.ts` (currently excluded)
Full integration test that imports the `marklogic` module. To use this:
1. Build/link the package locally (`npm link`)
2. Remove it from the exclude list in `tsconfig.json`
3. Run `npm run test:types` again

## Adding More Type Tests

As you add more interfaces to `marklogic.d.ts`, add corresponding test files here. The pattern is:

1. Create a `.test.ts` file
2. Write TypeScript code that uses the types
3. Include examples that should work AND commented examples that should fail
4. Run `npm run test:types` to verify

## Why This Approach?

TypeScript's compiler is the best way to test type definitions because:
Expand Down
152 changes: 152 additions & 0 deletions test-typescript/connection-methods.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/

/**
* TypeScript type checking tests for connection-related methods.
*
* This file validates:
* - checkConnection() return type
* - release() method
* - releaseClient() standalone function
*
* These tests are compiled but NOT executed - they verify type correctness only.
* Run with: npm run test:types
*/

// Create test types that should match the actual marklogic types
type ConnectionCheckResult = {
connected: boolean;
httpStatusCode?: number;
httpStatusMessage?: string;
};

type DatabaseClient = {
checkConnection(): Promise<ConnectionCheckResult>;
release(): void;
};

type DatabaseClientConfig = {
host?: string;
port?: number;
user?: string;
password?: string;
};

// Simulate the marklogic module interface
type MarkLogicModule = {
createDatabaseClient(config: DatabaseClientConfig): DatabaseClient;
releaseClient(client: DatabaseClient): void;
};

// Test checkConnection() return type
async function testCheckConnection(marklogic: MarkLogicModule) {
const client = marklogic.createDatabaseClient({
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin'
});

// Should return a Promise<ConnectionCheckResult>
const result = await client.checkConnection();

// result.connected should be boolean
const isConnected: boolean = result.connected;

// When not connected, should have optional error properties
if (!result.connected) {
const statusCode: number | undefined = result.httpStatusCode;
const statusMessage: string | undefined = result.httpStatusMessage;

console.log(`Connection failed: ${statusCode} - ${statusMessage}`);
}

return isConnected;
}

// Test release() method on client
function testRelease(marklogic: MarkLogicModule) {
const client = marklogic.createDatabaseClient({
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin'
});

// Should be callable with no return value
client.release();

// This is the correct usage pattern
}

// Test releaseClient() standalone function
function testReleaseClientFunction(marklogic: MarkLogicModule) {
const client = marklogic.createDatabaseClient({
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin'
});

// Should accept a DatabaseClient and return void
marklogic.releaseClient(client);

// This is equivalent to client.release()
}

// Test proper cleanup pattern
async function testProperCleanupPattern(marklogic: MarkLogicModule) {
const client = marklogic.createDatabaseClient({
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin'
});

try {
const result = await client.checkConnection();
if (result.connected) {
console.log('Connected successfully!');
// Do database operations...
} else {
console.error(`Connection failed: ${result.httpStatusCode}`);
}
} finally {
// Always clean up resources
client.release();
}
}

// Test ConnectionCheckResult structure
const successResult: ConnectionCheckResult = {
connected: true
};

const failureResult: ConnectionCheckResult = {
connected: false,
httpStatusCode: 401,
httpStatusMessage: 'Unauthorized'
};

// These should cause errors if uncommented:
// const invalidResult1: ConnectionCheckResult = {
// connected: 'yes' // Error: should be boolean
// };

// const invalidResult2: ConnectionCheckResult = {
// connected: true,
// httpStatusCode: 'error' // Error: should be number
// };

console.log('✅ Connection method types validated!');

// Export to prevent "unused" errors
export {
testCheckConnection,
testRelease,
testReleaseClientFunction,
testProperCleanupPattern,
successResult,
failureResult
};
19 changes: 19 additions & 0 deletions typescript-test-project/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Dependencies
node_modules/
package-lock.json

# Compiled output
*.js
*.js.map
*.d.ts

# Build artifacts
dist/
build/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~
79 changes: 79 additions & 0 deletions typescript-test-project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Test Project - Realistic TypeScript Usage

This is a **standalone npm project** that demonstrates how users will consume the MarkLogic Node.js Client with TypeScript support.

## Purpose

This folder serves as:
- A realistic demo of TypeScript integration for colleagues and users
- A quick testing ground for new TypeScript features
- Validation that the library works as an installed npm package
- A showcase of IntelliSense and type safety in action

## Quick Start

### 1. Setup (First Time Only)
```bash
cd test-project
npm run setup
```

This will:
- Install the parent `marklogic` package (via `file:..`)
- Install TypeScript and type dependencies
- Set up everything needed for type checking

### 2. Test TypeScript Types
```bash
npm test
# or
npm run typecheck
```

This runs TypeScript's compiler in check-only mode (no JS output).

### 3. Edit and Experiment
Open `test.ts` in your IDE (VS Code, IntelliJ, etc.) and start typing:
- You'll get **autocomplete** for all config properties
- **Hover** over methods to see their signatures
- **IntelliSense** shows available options (like authType values)
- Type **errors are highlighted** in real-time

## How It Works

This project installs the parent `marklogic` package using npm's `file:..` protocol, which:
- Simulates a real npm install
- Picks up the `types` field from `package.json`
- Loads `marklogic.d.ts` automatically
- Provides full TypeScript support

## Demo This to Colleagues

1. **Show autocomplete**: In `test.ts`, type `marklogic.createDatabaseClient({` and watch the suggestions appear
2. **Show type safety**: Try setting `authType: 'invalid'` - TypeScript catches it!
3. **Show IntelliSense**: Hover over `checkConnection()` to see its return type
4. **Show error detection**: Run `npm test` with an invalid config to see type errors

## Files

- `package.json` - Standard npm package configuration
- `tsconfig.json` - TypeScript compiler configuration
- `test.ts` - Example TypeScript code using the marklogic client
- `.gitignore` - Ignores node_modules and build artifacts

## Updating After Changes

If you make changes to the parent `marklogic` package:

```bash
# Quick way - just reinstall the local package
npm install ..

# Or full clean reinstall
rm -rf node_modules package-lock.json
npm run setup
```

## Note

This is a **development/testing project only** - it's not meant to be published. The `"private": true` flag prevents accidental publishing to npm.
25 changes: 25 additions & 0 deletions typescript-test-project/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "marklogic-typescript-test-project",
"version": "1.0.0",
"description": "Test project for validating MarkLogic Node.js Client TypeScript definitions",
"private": true,
"scripts": {
"setup": "npm install .. && npm install",
"typecheck": "tsc --noEmit",
"test": "npm run typecheck"
},
"keywords": [
"marklogic",
"typescript",
"test"
],
"author": "",
"license": "Apache-2.0",
"devDependencies": {
"@types/node": "^22.10.1",
"typescript": "^5.7.2"
},
"dependencies": {
"marklogic": "file:.."
}
}
Loading
Loading