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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ jazz.config.*.json
# IDE
CLAUDE.md
.kiro/
.agent/
10 changes: 7 additions & 3 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default [
ignores: ["**/*.test.ts"],
languageOptions: {
parserOptions: {
project: "./tsconfig.json",
project: ["./tsconfig.json", "./tsconfig.build.json"],
tsconfigRootDir,
},
globals: {
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"url": "https://github.com/lvndry/jazz/issues"
},
"scripts": {
"build": "bun build src/main.ts --outfile dist/main.js --target node --minify && tsc --emitDeclarationOnly",
"build": "bun run scripts/build.ts",
"typecheck": "bun run tsc --noEmit",
"dev": "bun --watch src/main.ts",
"start": "bun dist/main.js",
Expand Down Expand Up @@ -74,6 +74,8 @@
"@effect/platform": "^0.90.10",
"@effect/platform-node": "^0.96.1",
"@effect/workflow": "^0.9.6",
"@googleapis/calendar": "^14.2.0",
"@googleapis/gmail": "^16.1.1",
"@inkjs/ui": "^2.0.0",
"@inquirer/prompts": "^8.2.0",
"@modelcontextprotocol/sdk": "^1.25.2",
Expand All @@ -87,7 +89,7 @@
"exa-js": "^2.0.12",
"fast-glob": "^3.3.3",
"fs-extra": "^11.3.3",
"googleapis": "^159.0.0",
"googleapis-common": "^8.0.1",
"gray-matter": "^4.0.3",
"ink": "^6.6.0",
"ink-big-text": "^2.0.0",
Expand Down
59 changes: 59 additions & 0 deletions scripts/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
type SpawnResult = {
readonly exitCode: number | null;
readonly stdout: string;
readonly stderr: string;
};

function run(command: string[], opts?: { readonly cwd?: string }): SpawnResult {
const proc = Bun.spawnSync(command, {
...(opts?.cwd ? { cwd: opts.cwd } : {}),
stdout: "pipe",
stderr: "pipe",
});

return {
exitCode: proc.exitCode,
stdout: new TextDecoder().decode(proc.stdout),
stderr: new TextDecoder().decode(proc.stderr),
};
}

function main(): void {
const banner = "#!/usr/bin/env node";
const outfile = "dist/main.js";

const buildArgs = [
"bun",
"build",
"src/entry.ts",
"--outfile",
outfile,
"--target",
"node",
"--minify",
"--external",
"react",
"--external",
"ink",
"--external",
"ink-gradient",
"--external",
"cfonts",
"--external",
"ink-big-text",
"--banner",
banner,
];

const build = run(buildArgs);
if (build.stdout.length > 0) process.stdout.write(build.stdout);
if (build.stderr.length > 0) process.stderr.write(build.stderr);
if (build.exitCode !== 0) throw new Error(`Build failed with exit code ${build.exitCode}`);

const tsc = run(["bun", "run", "tsc", "--emitDeclarationOnly"]);
if (tsc.stdout.length > 0) process.stdout.write(tsc.stdout);
if (tsc.stderr.length > 0) process.stderr.write(tsc.stderr);
if (tsc.exitCode !== 0) throw new Error(`TypeScript failed with exit code ${tsc.exitCode}`);
}

main();
26 changes: 0 additions & 26 deletions scripts/debug-keys.mjs

This file was deleted.

48 changes: 0 additions & 48 deletions scripts/debug-parser.mjs

This file was deleted.

16 changes: 16 additions & 0 deletions src/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* CLI bootstrap entrypoint.
*
* This file runs before the rest of the app is loaded so we can configure the
* Node.js process (e.g. suppress known noisy deprecation warnings) prior to
* importing the main CLI module and its dependency tree.
*/

// Suppress DeprecationWarning output (including Node's `punycode` warning coming
// from transitive dependencies on newer Node versions).
process.noDeprecation = true;

void import("./main").catch((error) => {
console.error("Fatal error:", error);
throw error;
});
1 change: 0 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import { Effect } from "effect";
import { createCLIApp } from "./cli/cli-app";

Expand Down
8 changes: 4 additions & 4 deletions src/services/calendar.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { FileSystem } from "@effect/platform";
import { auth, type calendar_v3 } from "@googleapis/calendar";
import { beforeEach, describe, expect, it, mock } from "bun:test";
import { Effect, Either } from "effect";
import { google, type calendar_v3 } from "googleapis";
import { CalendarServiceResource } from "./calendar";
import { CalendarService } from "../core/interfaces/calendar";
import type { TerminalService } from "../core/interfaces/terminal";
import { CalendarAuthenticationError, CalendarOperationError } from "../core/types";


// Helper constant for test tokens with required scopes
const TEST_TOKEN_WITH_SCOPES = JSON.stringify({
access_token: "test",
Expand All @@ -18,7 +17,7 @@ const TEST_TOKEN_WITH_SCOPES = JSON.stringify({
describe("CalendarService", () => {
let mockFileSystem: FileSystem.FileSystem;
let mockCalendar: calendar_v3.Calendar;
let mockOAuthClient: InstanceType<typeof google.auth.OAuth2>;
let mockOAuthClient: InstanceType<typeof auth.OAuth2>;
let mockRequireCredentials: () => Effect.Effect<void, CalendarAuthenticationError>;
let mockTerminal: TerminalService;
let calendarService: CalendarService;
Expand All @@ -45,7 +44,7 @@ describe("CalendarService", () => {
get credentials() {
return credentials;
},
} as unknown as InstanceType<typeof google.auth.OAuth2>;
} as unknown as InstanceType<typeof auth.OAuth2>;

// Mock Calendar API client
mockCalendar = {
Expand Down Expand Up @@ -76,6 +75,7 @@ describe("CalendarService", () => {
debug: mock(() => Effect.void),
heading: mock(() => Effect.void),
list: mock(() => Effect.void),
updateLog: mock(() => Effect.void),
ask: mock(() => Effect.succeed("")),
password: mock(() => Effect.succeed("")),
select: mock(() => Effect.succeed("")),
Expand Down
Loading