Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
47baf27
feat: Added login method
kevinwang5658 Jul 16, 2025
78d5dd6
feat: Added connect integration with codify-dashboard
kevinwang5658 Jul 27, 2025
45cb8ca
feat: switched to hono server and added cors support
kevinwang5658 Jul 27, 2025
83bc13f
feat: switched to express
kevinwang5658 Jul 28, 2025
7cb3972
chore: refactored apply flow to use express
kevinwang5658 Jul 29, 2025
4c2759e
Added login helper and trying out parser abstraction
kevinwang5658 Sep 2, 2025
5630319
Added ability to load, apply and plan cloud files
kevinwang5658 Sep 3, 2025
38b2414
Moved login init to base command. Fixes
kevinwang5658 Sep 5, 2025
b73f126
Added new codify file resolution logic. WIP default document endpoint…
kevinwang5658 Sep 5, 2025
aa23381
Added path as an arg to apply and plan
kevinwang5658 Sep 5, 2025
487159f
Added path as an arg to validate
kevinwang5658 Sep 5, 2025
5976346
Fixed import logic to support cloud files
kevinwang5658 Sep 6, 2025
69f8ae1
Fixed login bugs.
kevinwang5658 Sep 12, 2025
f5eddbc
Fixed codify apply via connect to supply tmpFile path. Added helpful …
kevinwang5658 Sep 12, 2025
5289fd3
Switched to socketIO
kevinwang5658 Sep 15, 2025
7faf88f
Switched back to websockets instead of socket io
kevinwang5658 Sep 15, 2025
5984c56
Prevent multiple pty instances from being created
kevinwang5658 Sep 16, 2025
2cf0b95
Improved the command handler to support more variations
kevinwang5658 Sep 16, 2025
e031dfd
Fixed build bugs. Moved uuid to dependency. Fixed entry points that w…
kevinwang5658 Sep 16, 2025
ef61320
Improved session ending logic.
kevinwang5658 Sep 17, 2025
421e152
Added missing import flag
kevinwang5658 Sep 24, 2025
dae7277
Changed connect commands to use rootCommand that way it updates with …
kevinwang5658 Sep 24, 2025
add4147
Refactored how commands are handled. Allows for greater flexibility.
kevinwang5658 Sep 25, 2025
ddf8ba3
Added import handler
kevinwang5658 Sep 25, 2025
90b9578
Added concept of clientId. Added import writer
kevinwang5658 Sep 25, 2025
3643c4a
Re-worked login to get email, userId, claims directly from token. Swi…
kevinwang5658 Oct 1, 2025
ad81e8f
Removed extraneous logs. Added message for codify edit
kevinwang5658 Oct 1, 2025
441d624
Added install beta script. Fixed urls to point to dashboard.codifycli…
kevinwang5658 Oct 2, 2025
904ac3f
Fixed login behavior for connect and edit. Added log out command
kevinwang5658 Oct 2, 2025
aad8e5a
Add new refresh command
kevinwang5658 Oct 21, 2025
26ba958
Changed the parameterless import to mimic init (auto import everything)
kevinwang5658 Oct 21, 2025
a76a640
Added refresh method to connect and fixed bugs
kevinwang5658 Oct 21, 2025
b24f2a9
Fixed API calls to parse error messages as non-json
kevinwang5658 Oct 21, 2025
92bf7b3
Fixed bugs:
kevinwang5658 Oct 22, 2025
cbe9334
Added --updateExisting flag for import command. Made refresh orchestr…
kevinwang5658 Oct 22, 2025
f40e04c
Fixed file modification calculator handling of an empty file '[]'. Ad…
kevinwang5658 Oct 22, 2025
c186cd0
Fixed file modification calculator handling of an empty file '[]'. Ad…
kevinwang5658 Oct 22, 2025
2b5e4fa
fix: Fixed bugs with refresh and import
kevinwang5658 Oct 25, 2025
7604bf2
feat: Added support for Codify remote files
kevinwang5658 Oct 27, 2025
a681d7f
fix: Bug fix for files that don't currently exist. Import confirmatio…
kevinwang5658 Oct 27, 2025
821bef6
fix: Bug fix for MacOS oclif installer bug. It doesn't clear the ocli…
kevinwang5658 Nov 16, 2025
432614a
feat: Added auto complete, additional version flags, additional help …
kevinwang5658 Nov 17, 2025
028766a
fix: Added init command
kevinwang5658 Nov 20, 2025
989cad3
Added new finish event to unify sending the remote result back to the…
kevinwang5658 Nov 21, 2025
2ecee5e
Added the useful ability to kill the previous codify connect so you d…
kevinwang5658 Nov 21, 2025
f48c6ef
fix: Moved kill port to dependencies
kevinwang5658 Nov 22, 2025
5fb7d70
feat: Added connection start time and connection termination
kevinwang5658 Dec 3, 2025
46b3259
feat: Refactored the initialization process to return a resource defi…
kevinwang5658 Dec 13, 2025
6c96b0a
feat: Added sensitive parameter filtering to import and init. Added s…
kevinwang5658 Dec 13, 2025
5d9b8be
feat: Added improvements to import and init saving of results
kevinwang5658 Dec 13, 2025
780ad3e
feat: Improved init experience (always new project for init)
kevinwang5658 Dec 13, 2025
130402a
feat: Fixed build issues and improved help
kevinwang5658 Dec 13, 2025
950c4dd
fix: Fixed existing tests
kevinwang5658 Dec 14, 2025
a2280ee
feat: Added CLI logins without the browser
kevinwang5658 Dec 14, 2025
5584367
feat: Added test for connect + improvements and fixes
kevinwang5658 Dec 14, 2025
5d311dc
feat: Added test for connect commands (apply, plan, import, etc) + im…
kevinwang5658 Dec 14, 2025
4b37f78
feat: Added additional tests for edit, login and refresh
kevinwang5658 Dec 14, 2025
f2bf0e7
feat: Add readme and license
kevinwang5658 Dec 14, 2025
441ab31
feat: Upgrade to node 22
kevinwang5658 Dec 14, 2025
1871937
fix: Test and type fixes
kevinwang5658 Dec 14, 2025
acdeb77
fix: Temp disable socket-server tests
kevinwang5658 Dec 14, 2025
40eae06
fix: Enable one of the disabled tests
kevinwang5658 Dec 14, 2025
93339f3
kevin/fix-tests (#50)
kevinwang5658 Dec 15, 2025
9e4e7cc
Fix: Bug fixes for help, and init using dev-dependency. Added extra c…
kevinwang5658 Dec 19, 2025
1bc02e7
feat: Added new spawn code using node-pty. Root and stdin are both su…
kevinwang5658 Dec 23, 2025
aeb6219
feat: Removed the spinner powered by log messages (caused pointer iss…
kevinwang5658 Dec 23, 2025
26cfda2
feat: Added codify test command that can spawn a tart vm to test codi…
kevinwang5658 Jan 3, 2026
f91cffa
feat: Improved the display for test. Added linux support on a macOS h…
kevinwang5658 Jan 3, 2026
c56b4d7
feat: Added support for validating by OS and distro. Added improved i…
kevinwang5658 Jan 22, 2026
d31a9df
feat: Allow beta plugins to be auto-magically be added when codify ve…
kevinwang5658 Jan 25, 2026
b55db9b
feat: Reverted commenting out xz
kevinwang5658 Jan 25, 2026
50c2d76
feat: Added os filtering for codify init command
kevinwang5658 Jan 30, 2026
749265c
feat: Updated github urls and description
kevinwang5658 Feb 10, 2026
6ece30e
feat: Force arch to be arm64. Added linux to uplaod script.
kevinwang5658 Feb 15, 2026
4ff8152
fix: Fixed sudo, reporters, os filtering, and others (mainly linux re…
kevinwang5658 Feb 22, 2026
b69734e
fix: Connect commands not working on other shells
kevinwang5658 Feb 24, 2026
a68b0ec
fix: Fixed running sudo commands on linux and commands with quotes
kevinwang5658 Feb 24, 2026
bb604b1
chore: switch to public npm @codifycli/ink-form package
kevinwang5658 Feb 24, 2026
2c57de7
fix: Fixed environment variables not carried over to sudo. Fixed bash…
kevinwang5658 Feb 26, 2026
b4cc362
fix: Fixed warnings on linux install. Bumped oclif version.
kevinwang5658 Feb 27, 2026
05f94cb
feat: Updated ink. Switched to dots instead of half circles. Move sle…
kevinwang5658 Mar 3, 2026
2758c84
fix: Fixed weird memory problem with using spinner and status message…
kevinwang5658 Mar 3, 2026
1b085df
feat: Improved coloring for progress display
kevinwang5658 Mar 3, 2026
4508491
fix: Fixed tests
kevinwang5658 Mar 4, 2026
2b4b2d6
chore: commit package-lock.json
kevinwang5658 Mar 4, 2026
cfe7fa6
fix: Linux tests and build errors
kevinwang5658 Mar 4, 2026
920fb9f
feat: Allow CI builds to run on both macOS and linux
kevinwang5658 Mar 4, 2026
6ae774b
feat: Improved test command and added file syncing (#56)
kevinwang5658 Mar 6, 2026
03320ad
feat: Added test to list of remote commands
kevinwang5658 Mar 7, 2026
8decc0a
chore: Updated packages. Switched to @codifycli/schemas
kevinwang5658 Mar 7, 2026
9da6120
chore: Updated package-lock.json
kevinwang5658 Mar 7, 2026
6cadec4
feat: removed login requirement for connect command
kevinwang5658 Mar 7, 2026
fa69e91
fix: Remove github token code in github actions
kevinwang5658 Mar 8, 2026
54c6ef6
chore: Update to @codifycli/plugin-core and update version of @codify…
kevinwang5658 Mar 8, 2026
b3beab5
feat: Updated README
kevinwang5658 Mar 8, 2026
b7f97c9
chore: new package-lock.json
kevinwang5658 Mar 8, 2026
7c26073
feat: Add CLAUDE.md and updated the README.md
kevinwang5658 Mar 8, 2026
90b8e93
fix: Fix bugs with the test command
kevinwang5658 Mar 8, 2026
0a5eb91
chore: update version to 1.0.0
kevinwang5658 Mar 8, 2026
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
Prev Previous commit
Next Next commit
feat: Added test for connect commands (apply, plan, import, etc) + im…
…provements and fixes
  • Loading branch information
kevinwang5658 committed Dec 14, 2025
commit 5d311dc8c08c5c3fc87e81bfdf826e1a90063c69
3 changes: 2 additions & 1 deletion src/connect/http-routes/create-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import WebSocket from 'ws';
import { Session, SocketServer } from '../socket-server.js';

export enum ConnectCommand {
TERMINAL = 'terminal',
TERMINAL = 'start terminal',
APPLY = 'apply',
PLAN = 'plan',
IMPORT = 'import',
REFRESH = 'refresh',
INIT = 'init',
}

interface Params {
Expand Down
2 changes: 1 addition & 1 deletion src/connect/http-routes/handlers/apply-handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { spawn } from '@homebridge/node-pty-prebuilt-multiarch';
import { ConfigFileSchema } from 'codify-schemas';
import fs from 'node:fs/promises';
import * as fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { WebSocket } from 'ws';
Expand Down
2 changes: 1 addition & 1 deletion src/connect/http-routes/handlers/import-handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { spawn } from '@homebridge/node-pty-prebuilt-multiarch';
import { ConfigFileSchema } from 'codify-schemas';
import { diffChars } from 'diff';
import fs from 'node:fs/promises';
import * as fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { WebSocket } from 'ws';
Expand Down
2 changes: 0 additions & 2 deletions src/connect/http-routes/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ router.post('/session', (req, res) => {
}

const sessionId = socketServer.createSession(clientId);
console.log('Terminal session created!', sessionId)

return res.status(200).json({ sessionId });
})

Expand Down
4 changes: 2 additions & 2 deletions src/connect/http-routes/handlers/init-handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { spawn } from '@homebridge/node-pty-prebuilt-multiarch';
import { diffChars } from 'diff';
import fs from 'node:fs/promises';
import * as fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { WebSocket } from 'ws';
Expand Down Expand Up @@ -46,7 +46,7 @@ export function initHandler() {
}

return createCommandHandler({
name: ConnectCommand.IMPORT,
name: ConnectCommand.INIT,
spawnCommand,
onExit
});
Expand Down
6 changes: 3 additions & 3 deletions src/connect/http-routes/handlers/plan-handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { spawn } from '@homebridge/node-pty-prebuilt-multiarch';
import { ConfigFileSchema } from 'codify-schemas';
import fs from 'node:fs/promises';
import os from 'node:os';
import * as fs from 'node:fs/promises';
import * as os from 'node:os';
import path from 'node:path';
import { WebSocket } from 'ws';

Expand All @@ -25,7 +25,7 @@ export function planHandler() {

const tmpDir = await fs.mkdtemp(os.tmpdir());
const filePath = path.join(tmpDir, 'codify.jsonc');
await fs.writeFile(filePath, JSON.stringify(codifyConfig, null, 2));
await fs.writeFile(filePath, JSON.stringify(codifyConfig, null, 2), { });

session.additionalData.filePath = filePath;

Expand Down
4 changes: 2 additions & 2 deletions src/connect/http-routes/handlers/refresh-handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { spawn } from '@homebridge/node-pty-prebuilt-multiarch';
import { ConfigFileSchema } from 'codify-schemas';
import { diffChars } from 'diff';
import fs from 'node:fs/promises';
import * as fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { WebSocket } from 'ws';
Expand All @@ -26,7 +26,7 @@ export function refreshHandler() {
}

if (!type || !Object.values(RefreshType).includes(type as RefreshType)) {
throw new Error('Unable to parse import type');
throw new Error('Unable to parse refresh type');
}

if (type === RefreshType.REFRESH_SPECIFIC && (!resourceTypes || !Array.isArray(resourceTypes))) {
Expand Down
91 changes: 91 additions & 0 deletions src/connect/http-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import cors from 'cors';
import express, { json } from 'express';
// @ts-ignore
import killPort from 'kill-port'
import { Server } from 'node:http';
import open from 'open';

import { config } from '../config.js';
import { ProcessName, ctx } from '../events/context.js';
import { Reporter } from '../ui/reporters/reporter.js';
import { registerKillListeners } from '../utils/register-kill-listeners.js';
import router from './http-routes/router.js';

export async function createHttpServer(
connectionSecret: string,
reporter: Reporter,
openBrowser = true,
onOpen?: (connectionCode: string, server: Server) => void
): Promise<Server> {
const app = express();

app.use(cors({ origin: config.corsAllowedOrigins }))
app.use(json())
app.use(createAuthHandler(connectionSecret))
app.use(router);
app.use(errorHandler)

return listen(app, reporter, (server) => {
if (openBrowser) {
open(`${config.dashboardUrl}/connection/success?code=${connectionSecret}`)
console.log(`Open browser window to store code.

If unsuccessful manually enter the code:
${connectionSecret}`)
}

onOpen?.(connectionSecret, server);
});

}

function listen(app: express.Application, reporter: Reporter, onOpen: (server: Server) => void): Promise<Server> {
return new Promise((resolve) => {
const server = app.listen(config.connectServerPort, async (error) => {
if (error) {

// This whole below allows the user to terminate the existing instance and continue
// Use kill-port to terminate the existing instance
if (error.message.includes('EADDRINUSE')) {
const ifTerminate = await reporter.promptConfirmation('An instance of \'codify connect\' is already running. Do you want to terminate the existing instance and continue?');

if (!ifTerminate) {
console.error('\n\nExiting...')
process.exit(1);
}

ctx.processStarted(ProcessName.TERMINATE)
await reporter.displayProgress();
await killPort(config.connectServerPort);
ctx.processFinished(ProcessName.TERMINATE);
await reporter.hide();

setTimeout(() => {
ctx.log('Retrying connection...')
listen(app, reporter, onOpen).then((server) => resolve(server));
}, 300);
}
} else {
resolve(server);
onOpen(server);
}
});

registerKillListeners(() => server.close());
});
}

function createAuthHandler(connectionCode: string) {
return (req, res, next) => {
if (req.header('Authorization') !== connectionCode) {
return res.status(400).json({ error: 'Invalid authorization' })
}

next();
}
}

function errorHandler(err, req, res, next) {
console.log(err.message);
res.status(500).json({ error: err.message });
}
7 changes: 1 addition & 6 deletions src/connect/socket-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,7 @@ export class SocketServer {
private onUpgrade = (request: IncomingMessage, socket: Duplex, head: Buffer): void => {
const { pathname } = new URL(request.url!, 'ws://localhost:51040')

// Ignore all socket io so it does not interfere
if (pathname.includes('socket.io')) {
return;
}

if (/*! this.validateOrigin(request.headers.origin ?? request.headers.referer ?? '') || */ !this.validateConnectionSecret(request)) {
if (!this.validateConnectionSecret(request)) {
console.error('Unauthorized request. Connection code:', request.headers['sec-websocket-protocol']);
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n')
socket.destroy();
Expand Down
63 changes: 3 additions & 60 deletions src/orchestrators/connect.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import { Config } from '@oclif/core';
import cors from 'cors';
import express, { json } from 'express';
// @ts-ignore
import killPort from 'kill-port';
import { randomBytes } from 'node:crypto';
import { Server } from 'node:http';
import open from 'open';

import { config } from '../config.js';
import router from '../connect/http-routes/router.js';
import { createHttpServer } from '../connect/http-server.js';
import { LoginHelper } from '../connect/login-helper.js';
import { SocketServer } from '../connect/socket-server.js';
import { ProcessName, ctx } from '../events/context.js';
import { ctx } from '../events/context.js';
import { Reporter } from '../ui/reporters/reporter.js';
import { LoginOrchestrator } from './login.js';
import { registerKillListeners } from '../utils/register-kill-listeners.js';

export class ConnectOrchestrator {
static rootCommand: string;
Expand All @@ -31,60 +23,11 @@ export class ConnectOrchestrator {
this.nodeBinary = process.execPath;

const connectionSecret = ConnectOrchestrator.tokenGenerate()
const app = express();

app.use(cors({ origin: config.corsAllowedOrigins }))
app.use(json())
app.use(router);

const server = await ConnectOrchestrator.listen(app, reporter, (server) => {
if (openBrowser) {
open(`${config.dashboardUrl}/connection/success?code=${connectionSecret}`)
console.log(`Open browser window to store code.

If unsuccessful manually enter the code:
${connectionSecret}`)
}

onOpen?.(connectionSecret, server);
});

const server = await createHttpServer(connectionSecret, reporter, openBrowser, onOpen);
SocketServer.init(server, connectionSecret);
}

private static listen(app: express.Application, reporter: Reporter, onOpen: (server: Server) => void): Promise<Server> {
return new Promise((resolve) => {
const server = app.listen(config.connectServerPort, async (error) => {
if (error) {
if (error.message.includes('EADDRINUSE')) {
const ifTerminate = await reporter.promptConfirmation('An instance of \'codify connect\' is already running. Do you want to terminate the existing instance and continue?');

if (!ifTerminate) {
console.error('\n\nExiting...')
process.exit(1);
}

ctx.processStarted(ProcessName.TERMINATE)
await reporter.displayProgress();
await killPort(config.connectServerPort);
ctx.processFinished(ProcessName.TERMINATE);
await reporter.hide();

setTimeout(() => {
ctx.log('Retrying connection...')
ConnectOrchestrator.listen(app, reporter, onOpen).then((server) => resolve(server));
}, 300);

}
} else {
resolve(server);
onOpen(server);
}
});

registerKillListeners(() => server.close());
});
}

private static tokenGenerate(bytes = 4): string {
return Buffer.from(randomBytes(bytes)).toString('hex')
Expand Down
3 changes: 1 addition & 2 deletions test/orchestrator/connect/connect-command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ describe('Connect orchestrator tests', () => {
expect(portInUse).to.be.true;
expect(loginRunSpy).toHaveBeenCalledOnce();

done();
server.close();
done();
})

});
});

Expand Down
Loading
Loading