Skip to content

Commit

Permalink
Merge pull request #8 from zowe/node-sdk-sample
Browse files Browse the repository at this point in the history
Node sdk sample
  • Loading branch information
zFernand0 authored Jan 15, 2025
2 parents aeb6923 + d16e7b6 commit 5fc185f
Show file tree
Hide file tree
Showing 14 changed files with 408 additions and 0 deletions.
7 changes: 7 additions & 0 deletions node-sdk-sample/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* eslint-env node */
module.exports = {
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
root: true,
};
Empty file.
3 changes: 3 additions & 0 deletions node-sdk-sample/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
package-lock.json
lib/
9 changes: 9 additions & 0 deletions node-sdk-sample/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Change Log

All notable changes to the Zowe Node SDK Sample will be documented in this file.

## Recent Changes

### Enhancements

### Bug Fixes
56 changes: 56 additions & 0 deletions node-sdk-sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Zowe Node SDK Sample

## Requirements

You can clone the repository using `git`:

```
git clone https://github.com/zowe/zowe-client-samples.git
```

Extract the `node-sdk-sample` directory from the cloned repository to a new project.

You can install the requirements in a virtual environment with following commands:

```shell
cd node-sdk-sample
npm install
npm run build
```

## Quickstart

After you install the package, import the class SampleSdk from modules.

Below is a simple script of how to run the sample SDK, assuming the script file is located under the `node-sdk-sample/src` folder:

```typescript
import { Session } from "@zowe/imperative";
import { SampleSdk } from "./main";

(async () => {
const session: Session = new Session({
hostname: "jsonplaceholder.typicode.com",
});
const sdk = new SampleSdk(session);
console.log("\n=== Retrieving a Single Post ===");
console.log(await sdk.getPost(1));
})();

```

## Running The Sample

With `~/node-sdk-sample` as the working directory, issue the following command to run the sample:

```shell
npm start
```

## Running Integration and Unit Tests

With `~/node-sdk-sample` as the working directory, issue the following command to run integration and unit tests:

```shell
npx jest tests/
```
Empty file added node-sdk-sample/docs/.gitkeep
Empty file.
13 changes: 13 additions & 0 deletions node-sdk-sample/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
rootDir: './',
preset: 'ts-jest',
testEnvironment: 'node',
transform: {
'^.+\\.ts$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'json'],
testMatch: [
'<rootDir>/tests/**/*.test.ts',
],
verbose: true,
};
29 changes: 29 additions & 0 deletions node-sdk-sample/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "sdk-sample",
"version": "1.0.0",
"main": "script.js",
"type": "commonjs",
"scripts": {
"test": "jest",
"lint": "eslint src",
"build": "tsc",
"watch": "tsc -w",
"start": "npm run build && node lib/script.js"
},
"author": "Zowe",
"license": "EPL-2.0",
"description": "Zowe Client Node SDK Sample",
"devDependencies": {
"@types/jest": "^29.5.14",
"@typescript-eslint/eslint-plugin": "^8.19.1",
"@typescript-eslint/parser": "^8.19.1",
"@zowe/imperative": "^8.10.4",
"eslint": "^8.57.1",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"typescript": "^5.7.3"
},
"peerDependencies": {
"@zowe/imperative": "^8.0.0"
}
}
51 changes: 51 additions & 0 deletions node-sdk-sample/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

import { AbstractSession, RestClient } from "@zowe/imperative";

export interface IPost {
userId?: number;
id?: number;
title?: string;
body?: string;
}

export class SampleSdk {
public static readonly POSTS_URI = "/posts";

private session: AbstractSession;

constructor(session: AbstractSession) {
this.session = session;
}

public async listPosts(): Promise<IPost[]> {
return RestClient.getExpectJSON<IPost[]>(this.session, SampleSdk.POSTS_URI);
}

public async getPost(id: number): Promise<IPost> {
const resource = `${SampleSdk.POSTS_URI}/${id}`;
return RestClient.getExpectJSON<IPost>(this.session, resource);
}

public async createPost(post: IPost): Promise<IPost> {
return RestClient.postExpectJSON<IPost>(this.session, SampleSdk.POSTS_URI,[], JSON.stringify(post));
}

public async updatePost(id: number, post: IPost): Promise<IPost> {
const resource = `${SampleSdk.POSTS_URI}/${id}`;
return RestClient.putExpectJSON<IPost>(this.session, resource, [], JSON.stringify(post));
}

public async deletePost(id: number): Promise<unknown> {
const resource = `${SampleSdk.POSTS_URI}/${id}`;
return RestClient.deleteExpectJSON(this.session, resource);
}
}
47 changes: 47 additions & 0 deletions node-sdk-sample/src/script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* This program tests the functionality of SampleSdk by interacting with the
* JSONPlaceholder REST API.
*/

import { Session } from "@zowe/imperative";
import { SampleSdk, IPost } from "./main";

(async () => {
// Create a session for the RestClient
const session: Session = new Session({
hostname: "jsonplaceholder.typicode.com",
});

const sdk = new SampleSdk(session);

try {
// List all posts
console.log("\n=== Listing All Posts ===");
const allPosts = await sdk.listPosts();
console.log("All Posts:", allPosts.slice(0, 5));

// Create a new post
console.log("\n=== Creating a Post ===");
const newPost: IPost = { title: "Test Post", body: "This is a test post.", userId: 1 };
const createdPost = await sdk.createPost(newPost);
console.log("Created Post:", createdPost);

// Get the newly created post by ID
console.log("\n=== Retrieving a Single Post ===");
const singlePost = await sdk.getPost(1);
console.log("Single Post:", singlePost);

// Update the created post
console.log("\n=== Updating the Post ===");
const updatedPost: IPost = await sdk.updatePost(1, { title: "Updated Title" });
console.log("Updated Post:", updatedPost);

// Delete the created post
console.log("\n=== Deleting the Post ===");
const deleteResponse = await sdk.deletePost(1);
console.log("Deleted Post Response:", deleteResponse);

} catch (error) {
console.error("An error occurred:", error);
}
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Jest tests for SampleSdk to verify interaction with REST API endpoints.
*/

import { AbstractSession, RestClient } from "@zowe/imperative";
import { SampleSdk } from "../../src/main";

jest.mock("@zowe/imperative", () => ({
...jest.requireActual("@zowe/imperative"),
RestClient: {
getExpectJSON: jest.fn(),
postExpectJSON: jest.fn(),
putExpectJSON: jest.fn(),
deleteExpectJSON: jest.fn(),
},
}));

const mockedRestClient = RestClient as jest.Mocked<typeof RestClient>;

describe("SampleSdk", () => {
let sdk: SampleSdk;
let mockSession: AbstractSession;

beforeEach(() => {
mockSession = {} as AbstractSession;
sdk = new SampleSdk(mockSession);
});

it("listPosts should return an array of posts", async () => {
const mockPosts = [
{ id: 1, title: "Post 1", body: "Content 1", userId: 1 },
{ id: 2, title: "Post 2", body: "Content 2", userId: 2 },
];
mockedRestClient.getExpectJSON.mockResolvedValue(mockPosts);

const result = await sdk.listPosts();
expect(result).toEqual(mockPosts);
expect(mockedRestClient.getExpectJSON).toHaveBeenCalledWith(mockSession, SampleSdk.POSTS_URI);
});

it("getPost should retrieve a post by ID", async () => {
const mockPost = { id: 1, title: "Post 1", body: "Content 1", userId: 1 };
mockedRestClient.getExpectJSON.mockResolvedValue(mockPost);

const result = await sdk.getPost(1);
expect(result).toEqual(mockPost);
expect(mockedRestClient.getExpectJSON).toHaveBeenCalledWith(mockSession, `${SampleSdk.POSTS_URI}/1`);
});

it("createPost should create a post and return the created post", async () => {
const newPost = { title: "New Post", body: "Content", userId: 1 };
const mockCreatedPost = { ...newPost, id: 101 };
mockedRestClient.postExpectJSON.mockResolvedValue(mockCreatedPost);

const result = await sdk.createPost(newPost);
expect(result).toEqual(mockCreatedPost);
expect(mockedRestClient.postExpectJSON).toHaveBeenCalledWith(mockSession, SampleSdk.POSTS_URI, [], JSON.stringify(newPost));
});

it("updatePost should update a post and return the updated post", async () => {
const updatedPost = { title: "Updated Title", body: "Updated Content", userId: 1 };
const mockUpdatedPost = { ...updatedPost, id: 1 };
mockedRestClient.putExpectJSON.mockResolvedValue(mockUpdatedPost);

const result = await sdk.updatePost(1, updatedPost);
expect(result).toEqual(mockUpdatedPost);
expect(mockedRestClient.putExpectJSON).toHaveBeenCalledWith(
mockSession,
`${SampleSdk.POSTS_URI}/1`,
[],
JSON.stringify(updatedPost)
);
});

it("deletePost should delete a post and return a success response", async () => {
const mockDeleteResponse = {};
mockedRestClient.deleteExpectJSON.mockResolvedValue(mockDeleteResponse);

const result = await sdk.deletePost(1);
expect(result).toEqual(mockDeleteResponse);
expect(mockedRestClient.deleteExpectJSON).toHaveBeenCalledWith(mockSession, `${SampleSdk.POSTS_URI}/1`);
});
});
14 changes: 14 additions & 0 deletions node-sdk-sample/tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES6",
"module": "CommonJS",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true
},
"exclude": [
"*.test.ts"
]
}
Loading

0 comments on commit 5fc185f

Please sign in to comment.