Skip to content

Commit

Permalink
add login and logout cli commands
Browse files Browse the repository at this point in the history
  • Loading branch information
jairad26 committed Oct 3, 2024
1 parent 2a3a53b commit c3baa09
Show file tree
Hide file tree
Showing 7 changed files with 7,859 additions and 2,990 deletions.
10,672 changes: 7,685 additions & 2,987 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,36 @@
"dependencies": {
"@oclif/core": "^4",
"@oclif/plugin-help": "^6",
"@oclif/plugin-plugins": "^5"
"@oclif/plugin-plugins": "^5",
"node-persist": "^4.0.3",
"open": "^10.1.0",
"proxyquire": "^2.1.3"
},
"devDependencies": {
"@babel/core": "^7.25.7",
"@babel/preset-env": "^7.25.7",
"@babel/preset-typescript": "^7.25.7",
"@oclif/prettier-config": "^0.2.1",
"@oclif/test": "^4",
"@types/chai": "^4",
"@types/jest": "^29.5.13",
"@types/mocha": "^10",
"@types/node": "^18",
"@types/node": "^18.19.54",
"@types/node-persist": "^3.1.8",
"@types/proxyquire": "^1.3.31",
"@types/sinon": "^17.0.3",
"babel-jest": "^29.7.0",
"chai": "^4",
"eslint": "^8",
"eslint-config-oclif": "^5",
"eslint-config-oclif-typescript": "^3",
"eslint-config-prettier": "^9",
"jest": "^29.7.0",
"mocha": "^10",
"oclif": "^4",
"shx": "^0.3.3",
"sinon": "^19.0.2",
"ts-jest": "^29.2.5",
"ts-node": "^10",
"typescript": "^5"
},
Expand Down
82 changes: 82 additions & 0 deletions src/commands/login/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {Command} from '@oclif/core'
import * as http from 'node:http'
import storage from 'node-persist'
import open from 'open'




export default class LoginIndex extends Command {
static override args = {
}

static override description = 'Login to Hypermode Console'

static override examples = [
'<%= config.bin %> <%= command.id %>',
]

static override flags = {
}

public async openLoginPage() {
// Open the Hypermode sign-in page in the default browser
const loginUrl = 'https://hypermode-stage.com/app/callback?port=5051&type=cli';
await open(loginUrl);
}

public async run(): Promise<void> {

// Initialize storage to persist JWT and email
await storage.init();

// Start a local server to capture JWT and email from redirect
const server = http.createServer(async (req, res) => {
const url = new URL(req.url ?? '', `http://${req.headers.host}`);

// Extract the JWT and email from query parameters
const token = url.searchParams.get('jwt');
const email = url.searchParams.get('email');

if (token && email) {
// Store JWT and email securely
await storage.setItem('jwt', token);
await storage.setItem('email', email);

// Send response back to browser indicating success
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Login successful! You can close this tab.');

// Close the server once JWT and email are captured
server.close();

// Confirm successful login in the CLI
this.log('Successfully logged in as ' + email + '! 🎉');
} else {
// Respond with an error if JWT or email is missing
res.writeHead(400, {'Content-Type': 'text/plain'});
res.end('JWT or email not found in the request.');
}
});

// Set a timeout for the server
const timeoutDuration = 300_000; // 300 seconds in milliseconds
const timeout = setTimeout(() => {
server.close();
throw new Error('Authentication timed out. Please try again.');
}, timeoutDuration);

// Listen on port 5051 for the redirect
server.listen(5051, 'localhost', () => {
// Open the Hypermode sign-in page in the default browser
this.log('Opening login page...');
this.openLoginPage();
this.log('Waiting for the login callback on port 5051...');
});

// Ensure the timeout is cleared if the server closes successfully
server.on('close', () => {
clearTimeout(timeout);
});
}
}
30 changes: 30 additions & 0 deletions src/commands/logout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {Command} from '@oclif/core'
import storage from 'node-persist'

export default class LogoutIndex extends Command {
static override args = {
}

static override description = 'Logout of Hypermode Console in the CLI'

static override examples = [
'<%= config.bin %> <%= command.id %>',
]

static override flags = {
}

public async run(): Promise<void> {
await storage.init();
const email = await storage.getItem('email');
if (!email) {
this.log('Not logged in.');
return;
}

console.log('Logging out of email: ' + email);

await storage.removeItem('jwt');
await storage.removeItem('email');
}
}
25 changes: 25 additions & 0 deletions test/commands/login/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// import {runCommand} from '@oclif/test'
// import {expect} from 'chai'
// import sinon, { SinonStub } from 'sinon';

// import LoginIndex from '../../../src/commands/login/index';

describe('login', () => {
// let openLoginPageStub: SinonStub;

// beforeEach(() => {
// // Create a stub for the openLoginPage method
// openLoginPageStub = sinon.stub(LoginIndex.prototype, 'openLoginPage').returns(Promise.resolve());
// });

// afterEach(() => {
// // Restore all stubs after each test
// sinon.restore();
// });

// it('runs login cmd', async () => {
// const { stdout } = await runCommand('login');
// expect(stdout).to.contain('');
// expect(openLoginPageStub.calledOnce).to.be.true; // Ensure the method was called
// });
})
15 changes: 15 additions & 0 deletions test/commands/logout/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {runCommand} from '@oclif/test'
import {expect} from 'chai'
import storage from 'node-persist'

describe('logout', () => {
it('runs logout cmd', async () => {
await storage.init();
await storage.setItem('email', '[email protected]');
const {stdout} = await runCommand('logout')
expect(stdout).to.contain('[email protected]')

const email = await runCommand('logout')
expect(email.stdout).to.contain('Not logged in.')
})
})
7 changes: 6 additions & 1 deletion test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"extends": "../tsconfig",
"compilerOptions": {
"noEmit": true
"target": "es2020",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"types": ["jest", "@oclif/test"] // Add this line
},
"references": [
{"path": ".."}
Expand Down

0 comments on commit c3baa09

Please sign in to comment.