notican 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.env.example +14 -0
  2. package/README.md +175 -0
  3. package/dist/__fixtures__/index.d.ts +11 -0
  4. package/dist/__fixtures__/index.d.ts.map +1 -0
  5. package/dist/__fixtures__/index.js +160 -0
  6. package/dist/__fixtures__/index.js.map +1 -0
  7. package/dist/config.d.ts +17 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +37 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/github/client.d.ts +29 -0
  12. package/dist/github/client.d.ts.map +1 -0
  13. package/dist/github/client.js +121 -0
  14. package/dist/github/client.js.map +1 -0
  15. package/dist/handlers/index.d.ts +11 -0
  16. package/dist/handlers/index.d.ts.map +1 -0
  17. package/dist/handlers/index.js +35 -0
  18. package/dist/handlers/index.js.map +1 -0
  19. package/dist/handlers/issue.d.ts +6 -0
  20. package/dist/handlers/issue.d.ts.map +1 -0
  21. package/dist/handlers/issue.js +114 -0
  22. package/dist/handlers/issue.js.map +1 -0
  23. package/dist/handlers/pr.d.ts +6 -0
  24. package/dist/handlers/pr.d.ts.map +1 -0
  25. package/dist/handlers/pr.js +126 -0
  26. package/dist/handlers/pr.js.map +1 -0
  27. package/dist/handlers/push.d.ts +7 -0
  28. package/dist/handlers/push.d.ts.map +1 -0
  29. package/dist/handlers/push.js +151 -0
  30. package/dist/handlers/push.js.map +1 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +37 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/notion/client.d.ts +40 -0
  36. package/dist/notion/client.d.ts.map +1 -0
  37. package/dist/notion/client.js +289 -0
  38. package/dist/notion/client.js.map +1 -0
  39. package/dist/processors/claude.d.ts +29 -0
  40. package/dist/processors/claude.d.ts.map +1 -0
  41. package/dist/processors/claude.js +245 -0
  42. package/dist/processors/claude.js.map +1 -0
  43. package/dist/server/index.d.ts +4 -0
  44. package/dist/server/index.d.ts.map +1 -0
  45. package/dist/server/index.js +77 -0
  46. package/dist/server/index.js.map +1 -0
  47. package/dist/types/index.d.ts +142 -0
  48. package/dist/types/index.d.ts.map +1 -0
  49. package/dist/types/index.js +12 -0
  50. package/dist/types/index.js.map +1 -0
  51. package/dist/watcher/notion-tasks.d.ts +10 -0
  52. package/dist/watcher/notion-tasks.d.ts.map +1 -0
  53. package/dist/watcher/notion-tasks.js +135 -0
  54. package/dist/watcher/notion-tasks.js.map +1 -0
  55. package/package.json +61 -0
  56. package/scripts/setup-notion.ts +216 -0
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.app = void 0;
7
+ exports.startServer = startServer;
8
+ const express_1 = __importDefault(require("express"));
9
+ const webhooks_1 = require("@octokit/webhooks");
10
+ const config_1 = require("../config");
11
+ const handlers_1 = require("../handlers");
12
+ const app = (0, express_1.default)();
13
+ exports.app = app;
14
+ const webhooks = new webhooks_1.Webhooks({
15
+ secret: config_1.config.GITHUB_WEBHOOK_SECRET,
16
+ });
17
+ // Raw body parser for webhook signature verification
18
+ app.use('/webhooks/github', express_1.default.raw({ type: 'application/json' }));
19
+ app.use(express_1.default.json());
20
+ // Health check endpoint
21
+ app.get('/health', (_req, res) => {
22
+ res.status(200).json({
23
+ status: 'ok',
24
+ timestamp: new Date().toISOString(),
25
+ service: 'notican-mcp-challange',
26
+ });
27
+ });
28
+ // GitHub webhook endpoint
29
+ app.post('/webhooks/github', async (req, res) => {
30
+ const signature = req.headers['x-hub-signature-256'];
31
+ const eventType = req.headers['x-github-event'];
32
+ const deliveryId = req.headers['x-github-delivery'];
33
+ if (!signature) {
34
+ res.status(401).json({ error: 'Missing signature header' });
35
+ return;
36
+ }
37
+ if (!eventType) {
38
+ res.status(400).json({ error: 'Missing X-GitHub-Event header' });
39
+ return;
40
+ }
41
+ const body = req.body;
42
+ const rawBody = body.toString('utf-8');
43
+ // Verify HMAC signature
44
+ const isValid = await webhooks.verify(rawBody, signature);
45
+ if (!isValid) {
46
+ console.error(`[Webhook] Invalid signature for delivery ${deliveryId}`);
47
+ res.status(401).json({ error: 'Invalid signature' });
48
+ return;
49
+ }
50
+ let payload;
51
+ try {
52
+ payload = JSON.parse(rawBody);
53
+ }
54
+ catch (_err) {
55
+ res.status(400).json({ error: 'Invalid JSON payload' });
56
+ return;
57
+ }
58
+ // Acknowledge immediately — GitHub expects < 10s response
59
+ res.status(202).json({ accepted: true, deliveryId });
60
+ // Process asynchronously
61
+ (0, handlers_1.routeEvent)(eventType, payload).catch((err) => {
62
+ console.error(`[Webhook] Error processing ${eventType} event (delivery: ${deliveryId}):`, err.message);
63
+ });
64
+ });
65
+ // Global error handler
66
+ app.use((err, _req, res, _next) => {
67
+ console.error('[Server] Unhandled error:', err.message);
68
+ res.status(500).json({ error: 'Internal server error' });
69
+ });
70
+ function startServer() {
71
+ app.listen(config_1.config.PORT, () => {
72
+ console.log(`[Server] Listening on port ${config_1.config.PORT}`);
73
+ console.log(`[Server] Webhook endpoint: POST http://localhost:${config_1.config.PORT}/webhooks/github`);
74
+ console.log(`[Server] Health check: GET http://localhost:${config_1.config.PORT}/health`);
75
+ });
76
+ }
77
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ export type GitHubEventType = 'pull_request' | 'push' | 'issues';
2
+ export interface PullRequestEvent {
3
+ action: string;
4
+ number: number;
5
+ pull_request: {
6
+ id: number;
7
+ number: number;
8
+ title: string;
9
+ body: string | null;
10
+ state: string;
11
+ merged: boolean;
12
+ merge_commit_sha: string | null;
13
+ base: {
14
+ ref: string;
15
+ sha: string;
16
+ };
17
+ head: {
18
+ ref: string;
19
+ sha: string;
20
+ };
21
+ user: {
22
+ login: string;
23
+ };
24
+ html_url: string;
25
+ diff_url: string;
26
+ patch_url: string;
27
+ additions: number;
28
+ deletions: number;
29
+ changed_files: number;
30
+ };
31
+ repository: GitHubRepository;
32
+ sender: GitHubUser;
33
+ }
34
+ export interface PushEvent {
35
+ ref: string;
36
+ before: string;
37
+ after: string;
38
+ commits: GitHubCommit[];
39
+ repository: GitHubRepository;
40
+ pusher: {
41
+ name: string;
42
+ email: string;
43
+ };
44
+ sender: GitHubUser;
45
+ }
46
+ export interface IssueEvent {
47
+ action: string;
48
+ issue: {
49
+ id: number;
50
+ number: number;
51
+ title: string;
52
+ body: string | null;
53
+ state: string;
54
+ html_url: string;
55
+ user: GitHubUser;
56
+ labels: Array<{
57
+ name: string;
58
+ color: string;
59
+ }>;
60
+ assignees: GitHubUser[];
61
+ };
62
+ repository: GitHubRepository;
63
+ sender: GitHubUser;
64
+ }
65
+ export type GitHubEvent = PullRequestEvent | PushEvent | IssueEvent;
66
+ export interface GitHubRepository {
67
+ id: number;
68
+ name: string;
69
+ full_name: string;
70
+ html_url: string;
71
+ default_branch: string;
72
+ }
73
+ export interface GitHubUser {
74
+ login: string;
75
+ avatar_url: string;
76
+ html_url: string;
77
+ }
78
+ export interface GitHubCommit {
79
+ id: string;
80
+ message: string;
81
+ timestamp: string;
82
+ url: string;
83
+ author: {
84
+ name: string;
85
+ email: string;
86
+ };
87
+ added: string[];
88
+ removed: string[];
89
+ modified: string[];
90
+ }
91
+ export interface ChangedFile {
92
+ filename: string;
93
+ status: 'added' | 'removed' | 'modified' | 'renamed';
94
+ additions: number;
95
+ deletions: number;
96
+ patch?: string;
97
+ }
98
+ export declare enum NotionDocType {
99
+ ADR = "ADR",
100
+ CHANGELOG = "CHANGELOG",
101
+ API_REF = "API_REF",
102
+ RUNBOOK = "RUNBOOK"
103
+ }
104
+ export interface ProcessedDoc {
105
+ type: NotionDocType;
106
+ title: string;
107
+ content: string;
108
+ metadata: Record<string, string | number | boolean | null>;
109
+ }
110
+ export interface GitHubIssuePayload {
111
+ title: string;
112
+ body: string;
113
+ labels: string[];
114
+ assignees?: string[];
115
+ }
116
+ export interface NotionTask {
117
+ id: string;
118
+ title: string;
119
+ body: string;
120
+ labels: string[];
121
+ assignees: string[];
122
+ githubIssueNumber?: number;
123
+ githubIssueUrl?: string;
124
+ githubSync: boolean;
125
+ }
126
+ export interface ADRContext {
127
+ prTitle: string;
128
+ prBody: string;
129
+ diff: string;
130
+ changedFiles: ChangedFile[];
131
+ prNumber: number;
132
+ prUrl: string;
133
+ author: string;
134
+ }
135
+ export interface RunbookContext {
136
+ changedFiles: ChangedFile[];
137
+ commitMessages: string[];
138
+ ref: string;
139
+ repoName: string;
140
+ repoUrl: string;
141
+ }
142
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotionDocType = void 0;
4
+ // Notion document types
5
+ var NotionDocType;
6
+ (function (NotionDocType) {
7
+ NotionDocType["ADR"] = "ADR";
8
+ NotionDocType["CHANGELOG"] = "CHANGELOG";
9
+ NotionDocType["API_REF"] = "API_REF";
10
+ NotionDocType["RUNBOOK"] = "RUNBOOK";
11
+ })(NotionDocType || (exports.NotionDocType = NotionDocType = {}));
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;AAwGA,wBAAwB;AACxB,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,4BAAW,CAAA;IACX,wCAAuB,CAAA;IACvB,oCAAmB,CAAA;IACnB,oCAAmB,CAAA;AACrB,CAAC,EALW,aAAa,6BAAb,aAAa,QAKxB"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Start the Notion task watcher cron job.
3
+ * Polls every POLL_INTERVAL_SECONDS seconds for new tasks to sync to GitHub.
4
+ */
5
+ export declare function startWatcher(): void;
6
+ /**
7
+ * Find all Notion tasks marked for GitHub sync and create the corresponding issues.
8
+ */
9
+ export declare function syncPendingTasks(): Promise<void>;
10
+ //# sourceMappingURL=notion-tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notion-tasks.d.ts","sourceRoot":"","sources":["../../src/watcher/notion-tasks.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,wBAAgB,YAAY,IAAI,IAAI,CA+BnC;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCtD"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startWatcher = startWatcher;
7
+ exports.syncPendingTasks = syncPendingTasks;
8
+ const node_cron_1 = __importDefault(require("node-cron"));
9
+ const config_1 = require("../config");
10
+ const client_1 = require("../notion/client");
11
+ const client_2 = require("../github/client");
12
+ let isRunning = false;
13
+ /**
14
+ * Start the Notion task watcher cron job.
15
+ * Polls every POLL_INTERVAL_SECONDS seconds for new tasks to sync to GitHub.
16
+ */
17
+ function startWatcher() {
18
+ const intervalSeconds = config_1.config.POLL_INTERVAL_SECONDS;
19
+ // node-cron doesn't support arbitrary seconds intervals natively
20
+ // so we build an expression based on the configured interval
21
+ const cronExpression = buildCronExpression(intervalSeconds);
22
+ console.log(`[Watcher] Starting Notion task watcher — polling every ${intervalSeconds}s (${cronExpression})`);
23
+ node_cron_1.default.schedule(cronExpression, async () => {
24
+ if (isRunning) {
25
+ console.log('[Watcher] Previous sync still in progress — skipping this tick');
26
+ return;
27
+ }
28
+ isRunning = true;
29
+ try {
30
+ await syncPendingTasks();
31
+ }
32
+ catch (err) {
33
+ const error = err;
34
+ console.error(`[Watcher] Sync failed: ${error.message}`);
35
+ }
36
+ finally {
37
+ isRunning = false;
38
+ }
39
+ });
40
+ // Run once immediately on startup
41
+ syncPendingTasks().catch((err) => {
42
+ console.error(`[Watcher] Initial sync failed: ${err.message}`);
43
+ });
44
+ }
45
+ /**
46
+ * Find all Notion tasks marked for GitHub sync and create the corresponding issues.
47
+ */
48
+ async function syncPendingTasks() {
49
+ console.log('[Watcher] Checking for pending Notion tasks to sync...');
50
+ let tasks;
51
+ try {
52
+ tasks = await (0, client_1.getTasksToSync)();
53
+ }
54
+ catch (err) {
55
+ const error = err;
56
+ throw new Error(`Failed to fetch pending tasks from Notion: ${error.message}`);
57
+ }
58
+ if (tasks.length === 0) {
59
+ console.log('[Watcher] No pending tasks to sync');
60
+ return;
61
+ }
62
+ console.log(`[Watcher] Found ${tasks.length} task(s) to sync`);
63
+ const results = await Promise.allSettled(tasks.map((task) => syncTask(task)));
64
+ const succeeded = results.filter((r) => r.status === 'fulfilled').length;
65
+ const failed = results.filter((r) => r.status === 'rejected').length;
66
+ console.log(`[Watcher] Sync complete: ${succeeded} succeeded, ${failed} failed`);
67
+ results.forEach((result, idx) => {
68
+ if (result.status === 'rejected') {
69
+ console.error(`[Watcher] Task "${tasks[idx].title}" failed: ${result.reason.message}`);
70
+ }
71
+ });
72
+ }
73
+ /**
74
+ * Sync a single Notion task to GitHub by creating an issue.
75
+ */
76
+ async function syncTask(task) {
77
+ console.log(`[Watcher] Syncing task: "${task.title}" (Notion ID: ${task.id})`);
78
+ const issueBody = buildIssueBody(task);
79
+ let issueNumber;
80
+ let issueUrl;
81
+ try {
82
+ const result = await (0, client_2.createIssue)(config_1.config.GITHUB_OWNER, config_1.config.GITHUB_REPO, task.title, issueBody, task.labels.length > 0 ? task.labels : ['notion-task']);
83
+ issueNumber = result.number;
84
+ issueUrl = result.url;
85
+ }
86
+ catch (err) {
87
+ const error = err;
88
+ throw new Error(`GitHub issue creation failed: ${error.message}`);
89
+ }
90
+ try {
91
+ await (0, client_1.markTaskSynced)(task.id, issueNumber, issueUrl);
92
+ }
93
+ catch (err) {
94
+ const error = err;
95
+ // Issue was created but Notion update failed — log prominently
96
+ console.error(`[Watcher] CRITICAL: GitHub issue #${issueNumber} created but failed to mark Notion task ${task.id} as synced: ${error.message}`);
97
+ throw error;
98
+ }
99
+ console.log(`[Watcher] Task "${task.title}" synced — GitHub issue #${issueNumber}: ${issueUrl}`);
100
+ }
101
+ /**
102
+ * Build the GitHub issue body from a Notion task.
103
+ */
104
+ function buildIssueBody(task) {
105
+ const lines = [
106
+ `> This issue was automatically created from a Notion task.`,
107
+ `> **Notion Page ID:** \`${task.id}\``,
108
+ '',
109
+ ];
110
+ if (task.body) {
111
+ lines.push('## Description', '', task.body, '');
112
+ }
113
+ if (task.assignees.length > 0) {
114
+ lines.push('## Assignees', '', task.assignees.map((a) => `- @${a}`).join('\n'), '');
115
+ }
116
+ lines.push('---', `*Synced from Notion via [notican-mcp-challange](https://github.com/${config_1.config.GITHUB_OWNER}/${config_1.config.GITHUB_REPO})*`);
117
+ return lines.join('\n');
118
+ }
119
+ /**
120
+ * Convert a polling interval in seconds to a cron expression.
121
+ * Supports intervals of 30s, 60s, and any minute multiple up to 30 minutes.
122
+ */
123
+ function buildCronExpression(intervalSeconds) {
124
+ if (intervalSeconds < 60) {
125
+ // Run every N seconds using */N in seconds field (requires node-cron with seconds support)
126
+ return `*/${intervalSeconds} * * * * *`;
127
+ }
128
+ const intervalMinutes = Math.floor(intervalSeconds / 60);
129
+ if (intervalMinutes <= 1)
130
+ return '* * * * *'; // every minute
131
+ if (intervalMinutes <= 30)
132
+ return `*/${intervalMinutes} * * * *`;
133
+ return '*/30 * * * *'; // cap at 30 min
134
+ }
135
+ //# sourceMappingURL=notion-tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notion-tasks.js","sourceRoot":"","sources":["../../src/watcher/notion-tasks.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "notican",
3
+ "version": "1.0.0",
4
+ "description": "Autonomous Engineering Intelligence Hub: bidirectional GitHub and Notion sync powered by Claude AI",
5
+ "main": "dist/index.js",
6
+ "files": [
7
+ "dist",
8
+ "scripts",
9
+ ".env.example",
10
+ "README.md"
11
+ ],
12
+ "engines": {
13
+ "node": ">=22"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "scripts": {
19
+ "dev": "tsx watch src/index.ts",
20
+ "build": "tsc",
21
+ "start": "node dist/index.js",
22
+ "setup:notion": "tsx scripts/setup-notion.ts",
23
+ "test": "jest",
24
+ "test:watch": "jest --watch",
25
+ "test:coverage": "jest --coverage",
26
+ "lint": "eslint src --ext .ts"
27
+ },
28
+ "dependencies": {
29
+ "@anthropic-ai/sdk": "^0.39.0",
30
+ "@notionhq/client": "^2.2.15",
31
+ "@octokit/rest": "^20.1.1",
32
+ "@octokit/webhooks": "^13.4.0",
33
+ "dotenv": "^16.4.7",
34
+ "express": "^4.21.2",
35
+ "node-cron": "^3.0.3",
36
+ "zod": "^3.23.8"
37
+ },
38
+ "devDependencies": {
39
+ "@semantic-release/changelog": "^6.0.3",
40
+ "@semantic-release/commit-analyzer": "^13.0.1",
41
+ "@semantic-release/git": "^10.0.1",
42
+ "@semantic-release/github": "^12.0.6",
43
+ "@semantic-release/npm": "^13.1.5",
44
+ "@semantic-release/release-notes-generator": "^14.1.0",
45
+ "@types/express": "^4.17.21",
46
+ "@types/jest": "^29.5.14",
47
+ "@types/node": "^22.10.7",
48
+ "@types/node-cron": "^3.0.11",
49
+ "@types/supertest": "^7.2.0",
50
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
51
+ "@typescript-eslint/parser": "^8.57.0",
52
+ "conventional-changelog-conventionalcommits": "^9.3.0",
53
+ "eslint": "^9.18.0",
54
+ "jest": "^29.7.0",
55
+ "supertest": "^7.2.2",
56
+ "ts-jest": "^29.2.5",
57
+ "ts-node": "^10.9.2",
58
+ "tsx": "^4.19.2",
59
+ "typescript": "^5.7.3"
60
+ }
61
+ }