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.
- package/.env.example +14 -0
- package/README.md +175 -0
- package/dist/__fixtures__/index.d.ts +11 -0
- package/dist/__fixtures__/index.d.ts.map +1 -0
- package/dist/__fixtures__/index.js +160 -0
- package/dist/__fixtures__/index.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +37 -0
- package/dist/config.js.map +1 -0
- package/dist/github/client.d.ts +29 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +121 -0
- package/dist/github/client.js.map +1 -0
- package/dist/handlers/index.d.ts +11 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +35 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/issue.d.ts +6 -0
- package/dist/handlers/issue.d.ts.map +1 -0
- package/dist/handlers/issue.js +114 -0
- package/dist/handlers/issue.js.map +1 -0
- package/dist/handlers/pr.d.ts +6 -0
- package/dist/handlers/pr.d.ts.map +1 -0
- package/dist/handlers/pr.js +126 -0
- package/dist/handlers/pr.js.map +1 -0
- package/dist/handlers/push.d.ts +7 -0
- package/dist/handlers/push.d.ts.map +1 -0
- package/dist/handlers/push.js +151 -0
- package/dist/handlers/push.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/notion/client.d.ts +40 -0
- package/dist/notion/client.d.ts.map +1 -0
- package/dist/notion/client.js +289 -0
- package/dist/notion/client.js.map +1 -0
- package/dist/processors/claude.d.ts +29 -0
- package/dist/processors/claude.d.ts.map +1 -0
- package/dist/processors/claude.js +245 -0
- package/dist/processors/claude.js.map +1 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +77 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types/index.d.ts +142 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/watcher/notion-tasks.d.ts +10 -0
- package/dist/watcher/notion-tasks.d.ts.map +1 -0
- package/dist/watcher/notion-tasks.js +135 -0
- package/dist/watcher/notion-tasks.js.map +1 -0
- package/package.json +61 -0
- package/scripts/setup-notion.ts +216 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../src/handlers/issue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAczE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleIssueEvent = handleIssueEvent;
|
|
4
|
+
const config_1 = require("../config");
|
|
5
|
+
const client_1 = require("../notion/client");
|
|
6
|
+
/**
|
|
7
|
+
* Handle GitHub issue events.
|
|
8
|
+
*/
|
|
9
|
+
async function handleIssueEvent(payload) {
|
|
10
|
+
const { action, issue } = payload;
|
|
11
|
+
console.log(`[Issue Handler] action=${action} issue=#${issue.number} "${issue.title}"`);
|
|
12
|
+
if (action === 'opened') {
|
|
13
|
+
await handleIssueOpened(payload);
|
|
14
|
+
}
|
|
15
|
+
else if (action === 'closed') {
|
|
16
|
+
await handleIssueClosed(payload);
|
|
17
|
+
}
|
|
18
|
+
else if (action === 'reopened') {
|
|
19
|
+
await handleIssueReopened(payload);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log(`[Issue Handler] Ignoring action: ${action}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* When a GitHub issue is opened: create a linked task in Notion Tasks database.
|
|
27
|
+
*/
|
|
28
|
+
async function handleIssueOpened(payload) {
|
|
29
|
+
const { issue, repository } = payload;
|
|
30
|
+
const labels = issue.labels.map((l) => l.name);
|
|
31
|
+
const assignees = issue.assignees.map((a) => a.login);
|
|
32
|
+
const content = [
|
|
33
|
+
`## GitHub Issue #${issue.number}`,
|
|
34
|
+
`**URL:** ${issue.html_url}`,
|
|
35
|
+
`**Author:** ${issue.user.login}`,
|
|
36
|
+
`**Repository:** ${repository.full_name}`,
|
|
37
|
+
`**Labels:** ${labels.length > 0 ? labels.join(', ') : 'none'}`,
|
|
38
|
+
`**Assignees:** ${assignees.length > 0 ? assignees.join(', ') : 'unassigned'}`,
|
|
39
|
+
'',
|
|
40
|
+
'---',
|
|
41
|
+
'',
|
|
42
|
+
'## Description',
|
|
43
|
+
'',
|
|
44
|
+
issue.body ?? '*(no description provided)*',
|
|
45
|
+
].join('\n');
|
|
46
|
+
try {
|
|
47
|
+
const pageId = await (0, client_1.createPage)(config_1.config.NOTION_DATABASE_TASKS, issue.title, content, {
|
|
48
|
+
github_issue_number: issue.number,
|
|
49
|
+
github_issue_url: issue.html_url,
|
|
50
|
+
github_repo: repository.full_name,
|
|
51
|
+
github_sync: false, // Already synced — this came FROM GitHub
|
|
52
|
+
status: 'Open',
|
|
53
|
+
author: issue.user.login,
|
|
54
|
+
labels: labels.join(', '),
|
|
55
|
+
});
|
|
56
|
+
console.log(`[Issue Handler] Notion task created for issue #${issue.number}: page ${pageId}`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const error = err;
|
|
60
|
+
throw new Error(`Failed to create Notion task for issue #${issue.number}: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* When a GitHub issue is closed: update the linked Notion task status to Done.
|
|
65
|
+
*/
|
|
66
|
+
async function handleIssueClosed(payload) {
|
|
67
|
+
const { issue } = payload;
|
|
68
|
+
try {
|
|
69
|
+
const pageId = await (0, client_1.findPageByExternalId)(config_1.config.NOTION_DATABASE_TASKS, String(issue.number), 'github_issue_number');
|
|
70
|
+
if (!pageId) {
|
|
71
|
+
console.warn(`[Issue Handler] No Notion task found for issue #${issue.number} — skipping update`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
await client_1.notion.pages.update({
|
|
75
|
+
page_id: pageId,
|
|
76
|
+
properties: {
|
|
77
|
+
status: { select: { name: 'Done' } },
|
|
78
|
+
closed_at: {
|
|
79
|
+
date: { start: new Date().toISOString() },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
console.log(`[Issue Handler] Notion task ${pageId} marked as Done for issue #${issue.number}`);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
const error = err;
|
|
87
|
+
throw new Error(`Failed to update Notion task for closed issue #${issue.number}: ${error.message}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* When a GitHub issue is reopened: update the linked Notion task status back to Open.
|
|
92
|
+
*/
|
|
93
|
+
async function handleIssueReopened(payload) {
|
|
94
|
+
const { issue } = payload;
|
|
95
|
+
try {
|
|
96
|
+
const pageId = await (0, client_1.findPageByExternalId)(config_1.config.NOTION_DATABASE_TASKS, String(issue.number), 'github_issue_number');
|
|
97
|
+
if (!pageId) {
|
|
98
|
+
console.warn(`[Issue Handler] No Notion task found for issue #${issue.number} — skipping update`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
await client_1.notion.pages.update({
|
|
102
|
+
page_id: pageId,
|
|
103
|
+
properties: {
|
|
104
|
+
status: { select: { name: 'In Progress' } },
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
console.log(`[Issue Handler] Notion task ${pageId} marked as In Progress for issue #${issue.number}`);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const error = err;
|
|
111
|
+
throw new Error(`Failed to update Notion task for reopened issue #${issue.number}: ${error.message}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=issue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.js","sourceRoot":"","sources":["../../src/handlers/issue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.d.ts","sourceRoot":"","sources":["../../src/handlers/pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAOjD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcrF"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlePullRequestEvent = handlePullRequestEvent;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const config_1 = require("../config");
|
|
6
|
+
const client_1 = require("../github/client");
|
|
7
|
+
const claude_1 = require("../processors/claude");
|
|
8
|
+
const client_2 = require("../notion/client");
|
|
9
|
+
/**
|
|
10
|
+
* Handle pull_request events from GitHub.
|
|
11
|
+
*/
|
|
12
|
+
async function handlePullRequestEvent(payload) {
|
|
13
|
+
const { action, pull_request: pr, repository } = payload;
|
|
14
|
+
const owner = config_1.config.GITHUB_OWNER;
|
|
15
|
+
const repo = config_1.config.GITHUB_REPO;
|
|
16
|
+
console.log(`[PR Handler] action=${action} pr=#${pr.number} "${pr.title}"`);
|
|
17
|
+
if (action === 'closed' && pr.merged && pr.base.ref === repository.default_branch) {
|
|
18
|
+
await handleMergedPR(owner, repo, payload);
|
|
19
|
+
}
|
|
20
|
+
else if (action === 'opened' || action === 'ready_for_review') {
|
|
21
|
+
await handleOpenedPR(owner, repo, payload);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.log(`[PR Handler] Ignoring action: ${action}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* When a PR is merged to the default branch:
|
|
29
|
+
* 1. Fetch the full diff
|
|
30
|
+
* 2. Ask Claude to analyze and determine what docs to generate
|
|
31
|
+
* 3. Write docs to appropriate Notion databases
|
|
32
|
+
*/
|
|
33
|
+
async function handleMergedPR(owner, repo, payload) {
|
|
34
|
+
const { pull_request: pr } = payload;
|
|
35
|
+
console.log(`[PR Handler] PR #${pr.number} merged — fetching diff and generating docs`);
|
|
36
|
+
let diff;
|
|
37
|
+
try {
|
|
38
|
+
diff = await (0, client_1.getPRDiff)(owner, repo, pr.number);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const error = err;
|
|
42
|
+
console.error(`[PR Handler] Could not fetch diff: ${error.message}`);
|
|
43
|
+
// Fall back to generating just a changelog without diff analysis
|
|
44
|
+
diff = '';
|
|
45
|
+
}
|
|
46
|
+
// Always generate a changelog entry for merged PRs
|
|
47
|
+
try {
|
|
48
|
+
const changelog = await (0, claude_1.generateChangelog)(payload);
|
|
49
|
+
const externalId = `pr-${pr.number}`;
|
|
50
|
+
await (0, client_2.createOrUpdatePage)(config_1.config.NOTION_DATABASE_CHANGELOG, externalId, `${pr.title} (#${pr.number})`, changelog, {
|
|
51
|
+
github_pr_number: String(pr.number),
|
|
52
|
+
github_pr_url: pr.html_url,
|
|
53
|
+
author: pr.user.login,
|
|
54
|
+
merged_at: new Date().toISOString(),
|
|
55
|
+
});
|
|
56
|
+
console.log(`[PR Handler] Changelog created for PR #${pr.number}`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const error = err;
|
|
60
|
+
console.error(`[PR Handler] Failed to create changelog: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
// If we have a diff, do deeper AI analysis for ADRs / API Ref / Runbooks
|
|
63
|
+
if (diff) {
|
|
64
|
+
try {
|
|
65
|
+
const docs = await (0, claude_1.analyzeDiff)(diff, pr.title, pr.body ?? '');
|
|
66
|
+
for (const doc of docs) {
|
|
67
|
+
// Skip CHANGELOG — already handled above
|
|
68
|
+
if (doc.type === types_1.NotionDocType.CHANGELOG)
|
|
69
|
+
continue;
|
|
70
|
+
const databaseId = getDatabaseForDocType(doc.type);
|
|
71
|
+
if (!databaseId) {
|
|
72
|
+
console.warn(`[PR Handler] No database configured for doc type: ${doc.type}`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const externalId = `pr-${pr.number}-${doc.type}`;
|
|
76
|
+
await (0, client_2.createOrUpdatePage)(databaseId, externalId, doc.title, doc.content, {
|
|
77
|
+
...doc.metadata,
|
|
78
|
+
github_pr_number: String(pr.number),
|
|
79
|
+
github_pr_url: pr.html_url,
|
|
80
|
+
});
|
|
81
|
+
console.log(`[PR Handler] ${doc.type} doc created: "${doc.title}"`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
const error = err;
|
|
86
|
+
console.error(`[PR Handler] Failed to analyze diff for additional docs: ${error.message}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* When a PR is opened or marked ready for review:
|
|
92
|
+
* Generate a summary page for team context.
|
|
93
|
+
*/
|
|
94
|
+
async function handleOpenedPR(_owner, _repo, payload) {
|
|
95
|
+
const { pull_request: pr } = payload;
|
|
96
|
+
console.log(`[PR Handler] PR #${pr.number} opened — generating review summary`);
|
|
97
|
+
try {
|
|
98
|
+
const summary = await (0, claude_1.summarizePR)(payload);
|
|
99
|
+
await (0, client_2.createPage)(config_1.config.NOTION_DATABASE_CHANGELOG, `[Review] ${pr.title} (#${pr.number})`, summary, {
|
|
100
|
+
github_pr_number: String(pr.number),
|
|
101
|
+
github_pr_url: pr.html_url,
|
|
102
|
+
author: pr.user.login,
|
|
103
|
+
status: 'open',
|
|
104
|
+
});
|
|
105
|
+
console.log(`[PR Handler] Review summary created for PR #${pr.number}`);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
const error = err;
|
|
109
|
+
console.error(`[PR Handler] Failed to create review summary: ${error.message}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function getDatabaseForDocType(type) {
|
|
113
|
+
switch (type) {
|
|
114
|
+
case types_1.NotionDocType.ADR:
|
|
115
|
+
return config_1.config.NOTION_DATABASE_ADR;
|
|
116
|
+
case types_1.NotionDocType.CHANGELOG:
|
|
117
|
+
return config_1.config.NOTION_DATABASE_CHANGELOG;
|
|
118
|
+
case types_1.NotionDocType.API_REF:
|
|
119
|
+
return config_1.config.NOTION_DATABASE_API_REF;
|
|
120
|
+
case types_1.NotionDocType.RUNBOOK:
|
|
121
|
+
return config_1.config.NOTION_DATABASE_RUNBOOKS;
|
|
122
|
+
default:
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=pr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/handlers/pr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/handlers/push.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAA+B,MAAM,UAAU,CAAC;AA+CvE;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DvE"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlePushEvent = handlePushEvent;
|
|
4
|
+
const config_1 = require("../config");
|
|
5
|
+
const client_1 = require("../github/client");
|
|
6
|
+
const claude_1 = require("../processors/claude");
|
|
7
|
+
const client_2 = require("../notion/client");
|
|
8
|
+
// Patterns for different file categories
|
|
9
|
+
const API_PATTERNS = [
|
|
10
|
+
/routes?\//i,
|
|
11
|
+
/api\//i,
|
|
12
|
+
/controllers?\//i,
|
|
13
|
+
/endpoints?\//i,
|
|
14
|
+
/openapi/i,
|
|
15
|
+
/swagger/i,
|
|
16
|
+
/\.ya?ml$/i,
|
|
17
|
+
/graphql/i,
|
|
18
|
+
/schema\.(ts|js|json)$/i,
|
|
19
|
+
];
|
|
20
|
+
const INFRA_PATTERNS = [
|
|
21
|
+
/Dockerfile/i,
|
|
22
|
+
/docker-compose/i,
|
|
23
|
+
/k8s\//i,
|
|
24
|
+
/kubernetes\//i,
|
|
25
|
+
/helm\//i,
|
|
26
|
+
/terraform\//i,
|
|
27
|
+
/\.tf$/i,
|
|
28
|
+
/\.tfvars$/i,
|
|
29
|
+
/\.github\/workflows/i,
|
|
30
|
+
/ansible\//i,
|
|
31
|
+
/nginx/i,
|
|
32
|
+
];
|
|
33
|
+
const ARCH_PATTERNS = [
|
|
34
|
+
/package\.json$/i,
|
|
35
|
+
/tsconfig/i,
|
|
36
|
+
/webpack/i,
|
|
37
|
+
/vite\.config/i,
|
|
38
|
+
/babel\.config/i,
|
|
39
|
+
/jest\.config/i,
|
|
40
|
+
/src\/core\//i,
|
|
41
|
+
/src\/lib\//i,
|
|
42
|
+
/src\/shared\//i,
|
|
43
|
+
/middleware\//i,
|
|
44
|
+
/plugins?\//i,
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Handle push events from GitHub.
|
|
48
|
+
* Only process pushes to the default branch.
|
|
49
|
+
*/
|
|
50
|
+
async function handlePushEvent(payload) {
|
|
51
|
+
const { ref, repository, commits } = payload;
|
|
52
|
+
const defaultBranch = `refs/heads/${repository.default_branch}`;
|
|
53
|
+
if (ref !== defaultBranch) {
|
|
54
|
+
console.log(`[Push Handler] Ignoring push to ${ref} (not default branch)`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (!payload.after || payload.after === '0000000000000000000000000000000000000000') {
|
|
58
|
+
console.log('[Push Handler] Ignoring branch deletion event');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
console.log(`[Push Handler] Processing push to ${ref} with ${commits.length} commit(s)`);
|
|
62
|
+
const owner = config_1.config.GITHUB_OWNER;
|
|
63
|
+
const repo = config_1.config.GITHUB_REPO;
|
|
64
|
+
let changedFiles;
|
|
65
|
+
try {
|
|
66
|
+
changedFiles = await (0, client_1.getChangedFiles)(owner, repo, payload.after);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const error = err;
|
|
70
|
+
console.error(`[Push Handler] Failed to fetch changed files: ${error.message}`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const commitMessages = commits.map((c) => c.message.split('\n')[0]);
|
|
74
|
+
// Check for API file changes
|
|
75
|
+
const apiFiles = changedFiles.filter((f) => API_PATTERNS.some((p) => p.test(f.filename)));
|
|
76
|
+
if (apiFiles.length > 0) {
|
|
77
|
+
await handleAPIChanges(apiFiles, payload.after, repository.name).catch((err) => {
|
|
78
|
+
console.error(`[Push Handler] API ref update failed: ${err.message}`);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Check for infrastructure file changes
|
|
82
|
+
const infraFiles = changedFiles.filter((f) => INFRA_PATTERNS.some((p) => p.test(f.filename)));
|
|
83
|
+
if (infraFiles.length > 0) {
|
|
84
|
+
const runbookContext = {
|
|
85
|
+
changedFiles: infraFiles,
|
|
86
|
+
commitMessages,
|
|
87
|
+
ref,
|
|
88
|
+
repoName: repository.full_name,
|
|
89
|
+
repoUrl: repository.html_url,
|
|
90
|
+
};
|
|
91
|
+
await handleInfraChanges(runbookContext, payload.after).catch((err) => {
|
|
92
|
+
console.error(`[Push Handler] Runbook update failed: ${err.message}`);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Check for architecture-level changes
|
|
96
|
+
const archFiles = changedFiles.filter((f) => ARCH_PATTERNS.some((p) => p.test(f.filename)));
|
|
97
|
+
if (archFiles.length >= 3) {
|
|
98
|
+
// Only trigger ADR for significant arch changes (3+ files)
|
|
99
|
+
await handleArchChanges(archFiles, payload, commitMessages).catch((err) => {
|
|
100
|
+
console.error(`[Push Handler] ADR generation failed: ${err.message}`);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function handleAPIChanges(apiFiles, ref, repoName) {
|
|
105
|
+
console.log(`[Push Handler] ${apiFiles.length} API file(s) changed — updating API Reference`);
|
|
106
|
+
const content = await (0, claude_1.generateAPIRefUpdate)(apiFiles);
|
|
107
|
+
const externalId = `api-ref-${repoName}`;
|
|
108
|
+
await (0, client_2.createOrUpdatePage)(config_1.config.NOTION_DATABASE_API_REF, externalId, `API Reference — ${repoName}`, content, {
|
|
109
|
+
github_ref: ref,
|
|
110
|
+
last_updated: new Date().toISOString(),
|
|
111
|
+
changed_files: apiFiles.map((f) => f.filename).join(', '),
|
|
112
|
+
});
|
|
113
|
+
console.log('[Push Handler] API Reference updated in Notion');
|
|
114
|
+
}
|
|
115
|
+
async function handleInfraChanges(context, ref) {
|
|
116
|
+
console.log(`[Push Handler] ${context.changedFiles.length} infra file(s) changed — creating/updating Runbook`);
|
|
117
|
+
const content = await (0, claude_1.generateRunbook)(context);
|
|
118
|
+
const externalId = `runbook-${ref.slice(0, 12)}`;
|
|
119
|
+
const title = `Runbook: ${context.commitMessages[0] ?? 'Infrastructure Update'}`;
|
|
120
|
+
await (0, client_2.createOrUpdatePage)(config_1.config.NOTION_DATABASE_RUNBOOKS, externalId, title, content, {
|
|
121
|
+
github_ref: ref,
|
|
122
|
+
created_at: new Date().toISOString(),
|
|
123
|
+
changed_files: context.changedFiles.map((f) => f.filename).join(', '),
|
|
124
|
+
});
|
|
125
|
+
console.log('[Push Handler] Runbook created/updated in Notion');
|
|
126
|
+
}
|
|
127
|
+
async function handleArchChanges(archFiles, payload, commitMessages) {
|
|
128
|
+
console.log(`[Push Handler] ${archFiles.length} architecture file(s) changed — generating ADR`);
|
|
129
|
+
const adrContext = {
|
|
130
|
+
prTitle: commitMessages[0] ?? 'Architecture change via direct push',
|
|
131
|
+
prBody: commitMessages.join('\n'),
|
|
132
|
+
diff: archFiles
|
|
133
|
+
.filter((f) => f.patch)
|
|
134
|
+
.map((f) => `--- ${f.filename}\n${f.patch ?? ''}`)
|
|
135
|
+
.join('\n\n'),
|
|
136
|
+
changedFiles: archFiles,
|
|
137
|
+
prNumber: 0,
|
|
138
|
+
prUrl: payload.repository.html_url,
|
|
139
|
+
author: payload.pusher.name,
|
|
140
|
+
};
|
|
141
|
+
const content = await (0, claude_1.generateADR)(adrContext);
|
|
142
|
+
const externalId = `adr-push-${payload.after.slice(0, 12)}`;
|
|
143
|
+
const title = `ADR: ${commitMessages[0] ?? 'Architecture Decision'}`;
|
|
144
|
+
await (0, client_2.createOrUpdatePage)(config_1.config.NOTION_DATABASE_ADR, externalId, title, content, {
|
|
145
|
+
github_ref: payload.after,
|
|
146
|
+
author: payload.pusher.name,
|
|
147
|
+
created_at: new Date().toISOString(),
|
|
148
|
+
});
|
|
149
|
+
console.log('[Push Handler] ADR created in Notion');
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/handlers/push.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
require("dotenv/config");
|
|
4
|
+
// config import triggers env validation at startup — fail fast before anything else
|
|
5
|
+
const config_1 = require("./config");
|
|
6
|
+
const server_1 = require("./server");
|
|
7
|
+
const notion_tasks_1 = require("./watcher/notion-tasks");
|
|
8
|
+
console.log('='.repeat(60));
|
|
9
|
+
console.log(' Autonomous Engineering Intelligence Hub');
|
|
10
|
+
console.log(' GitHub ↔ Notion Bidirectional Sync');
|
|
11
|
+
console.log('='.repeat(60));
|
|
12
|
+
console.log(`[Main] Environment: ${process.env.NODE_ENV ?? 'development'}`);
|
|
13
|
+
console.log(`[Main] GitHub: ${config_1.config.GITHUB_OWNER}/${config_1.config.GITHUB_REPO}`);
|
|
14
|
+
console.log(`[Main] Poll interval: ${config_1.config.POLL_INTERVAL_SECONDS}s`);
|
|
15
|
+
// Start the Express webhook server
|
|
16
|
+
(0, server_1.startServer)();
|
|
17
|
+
// Start the Notion task watcher cron job
|
|
18
|
+
(0, notion_tasks_1.startWatcher)();
|
|
19
|
+
// Graceful shutdown
|
|
20
|
+
process.on('SIGTERM', () => {
|
|
21
|
+
console.log('[Main] SIGTERM received — shutting down gracefully');
|
|
22
|
+
process.exit(0);
|
|
23
|
+
});
|
|
24
|
+
process.on('SIGINT', () => {
|
|
25
|
+
console.log('[Main] SIGINT received — shutting down gracefully');
|
|
26
|
+
process.exit(0);
|
|
27
|
+
});
|
|
28
|
+
process.on('uncaughtException', (err) => {
|
|
29
|
+
console.error('[Main] Uncaught exception:', err.message);
|
|
30
|
+
console.error(err.stack);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
});
|
|
33
|
+
process.on('unhandledRejection', (reason) => {
|
|
34
|
+
console.error('[Main] Unhandled promise rejection:', reason);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yBAAuB;AACvB,oFAAoF;AACpF,qCAAkC;AAClC,qCAAuC;AACvC,yDAAsD;AAEtD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;AACxD,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;AACnD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,EAAE,CAAC,CAAC;AAC5E,OAAO,CAAC,GAAG,CAAC,kBAAkB,eAAM,CAAC,YAAY,IAAI,eAAM,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3E,OAAO,CAAC,GAAG,CAAC,yBAAyB,eAAM,CAAC,qBAAqB,GAAG,CAAC,CAAC;AAEtE,mCAAmC;AACnC,IAAA,oBAAW,GAAE,CAAC;AAEd,yCAAyC;AACzC,IAAA,2BAAY,GAAE,CAAC;AAEf,oBAAoB;AACpB,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;IACtC,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,MAAM,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Client } from '@notionhq/client';
|
|
2
|
+
import type { BlockObjectRequest } from '@notionhq/client/build/src/api-endpoints';
|
|
3
|
+
import type { NotionTask } from '../types';
|
|
4
|
+
declare const notion: Client;
|
|
5
|
+
/**
|
|
6
|
+
* Convert a markdown string to an array of Notion block objects.
|
|
7
|
+
* Handles headings, bullet lists, numbered lists, code blocks, and paragraphs.
|
|
8
|
+
*/
|
|
9
|
+
export declare function markdownToNotionBlocks(markdown: string): BlockObjectRequest[];
|
|
10
|
+
/**
|
|
11
|
+
* Create a new page in a Notion database.
|
|
12
|
+
* Returns the created page ID.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createPage(databaseId: string, title: string, content: string, metadata: Record<string, string | number | boolean | null>): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Update an existing Notion page's content by archiving old blocks and writing new ones.
|
|
17
|
+
*/
|
|
18
|
+
export declare function updatePage(pageId: string, content: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Find a Notion page in a database by a rich_text property matching an external ID.
|
|
21
|
+
* Returns the page ID if found, null otherwise.
|
|
22
|
+
*/
|
|
23
|
+
export declare function findPageByExternalId(databaseId: string, externalId: string, propertyName?: string): Promise<string | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Idempotent create-or-update: finds an existing page by externalId or creates a new one.
|
|
26
|
+
* Returns the page ID.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createOrUpdatePage(databaseId: string, externalId: string, title: string, content: string, metadata: Record<string, string | number | boolean | null>): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Query the Tasks database for pages where github_sync checkbox is true
|
|
31
|
+
* and github_issue_number is not yet set.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getTasksToSync(): Promise<NotionTask[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Mark a Notion task as synced by setting the github_issue_number and
|
|
36
|
+
* unchecking github_sync.
|
|
37
|
+
*/
|
|
38
|
+
export declare function markTaskSynced(pageId: string, issueNumber: number, issueUrl: string): Promise<void>;
|
|
39
|
+
export { notion };
|
|
40
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/notion/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EACV,kBAAkB,EAEnB,MAAM,0CAA0C,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,QAAA,MAAM,MAAM,QAA4C,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA6E7E;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,GACzD,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAgBD;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe/E;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,SAAqB,GAChC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBxB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,GACzD,OAAO,CAAC,MAAM,CAAC,CASjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CA4D5D;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
|