docs-api.mjs
139 lines 4.6 KB
Raw
sha256:700fafdd1afa490919f9515d660ca6e75456bcd5bb67513abcd8757a634c01f6 docs: record AIP-b SD-21 land (KN #308) Human 9 days ago
1 /**
2 * Unified docs connector route handlers (Drive + Notion).
3 *
4 * Dispatches by provider / connector.provider. Drive gate is live
5 * (`DOCS_OAUTH_GOOGLE_AUTHORIZED=true`); Notion stays off. Tests may pass
6 * authorizedOverride via opts (routes never do in prod).
7 *
8 * @see docs/KN-DOCS-SYNC-FREEZE.md §4.2
9 */
10
11 import {
12 connectorForClient,
13 getConnector,
14 listConnectors,
15 } from './docs-connector-store.mjs';
16 import {
17 createProductionGoogleDriveClient,
18 handleBeginDocsConnector,
19 handleDocsConnectorCallback,
20 handleImportDocsConnectorFiles,
21 handleListDocsConnectorFiles,
22 handleRevokeDocsConnector,
23 handleSyncDocsConnector,
24 isDocsGoogleOAuthEnabled,
25 } from './google-drive-connector.mjs';
26 import {
27 createProductionNotionClient,
28 handleBeginNotionConnector,
29 handleImportNotionConnectorFiles,
30 handleListNotionConnectorFiles,
31 handleRevokeNotionConnector,
32 handleSyncNotionConnector,
33 isDocsNotionHubKeyEnabled,
34 } from './notion-hub-connector.mjs';
35
36 /**
37 * @param {{ authorizedOverride?: boolean, googleOverride?: boolean, notionOverride?: boolean }} [opts]
38 */
39 export function isAnyDocsConnectorEnabled(opts = {}) {
40 const googleOpts = opts.googleOverride !== undefined
41 ? { authorizedOverride: opts.googleOverride }
42 : opts.authorizedOverride !== undefined
43 ? { authorizedOverride: opts.authorizedOverride }
44 : {};
45 const notionOpts = opts.notionOverride !== undefined
46 ? { authorizedOverride: opts.notionOverride }
47 : opts.authorizedOverride !== undefined
48 ? { authorizedOverride: opts.authorizedOverride }
49 : {};
50 return isDocsGoogleOAuthEnabled(googleOpts) || isDocsNotionHubKeyEnabled(notionOpts);
51 }
52
53 function notAuthorized() {
54 return { ok: false, status: 501, code: 'NOT_AUTHORIZED' };
55 }
56
57 /**
58 * POST api/v1/docs/connectors — begin Drive OAuth or Notion Hub-key connector.
59 * @param {object} ctx
60 */
61 export function handleBeginDocsProvider(ctx) {
62 const body = ctx.body && typeof ctx.body === 'object' && !Array.isArray(ctx.body) ? ctx.body : null;
63 const provider = body && typeof body.provider === 'string' ? body.provider : '';
64 if (provider === 'google-drive') {
65 return handleBeginDocsConnector(ctx);
66 }
67 if (provider === 'notion') {
68 return handleBeginNotionConnector(ctx);
69 }
70 if (!isAnyDocsConnectorEnabled({ authorizedOverride: ctx.authorizedOverride })) {
71 return notAuthorized();
72 }
73 return { ok: false, status: 400, code: 'PROVIDER_DENIED' };
74 }
75
76 /**
77 * GET api/v1/docs/connectors — list client-safe connectors (both providers).
78 * @param {object} ctx
79 */
80 export function handleListAllDocsConnectors(ctx) {
81 if (!isAnyDocsConnectorEnabled({ authorizedOverride: ctx.authorizedOverride })) {
82 return notAuthorized();
83 }
84 return {
85 ok: true,
86 status: 200,
87 payload: {
88 schema: 'knowtation.docs_connectors/v0',
89 connectors: listConnectors(ctx.dataDir, ctx.vaultId).map(connectorForClient),
90 },
91 };
92 }
93
94 /**
95 * @param {object} ctx
96 * @returns {Promise<object>}
97 */
98 export async function handleDocsConnectorCallbackUnified(ctx) {
99 return handleDocsConnectorCallback(ctx);
100 }
101
102 /**
103 * Dispatch list/import/sync/revoke by stored connector provider.
104 * @param {'list'|'import'|'sync'|'revoke'} action
105 * @param {object} ctx
106 */
107 export async function handleDocsConnectorAction(action, ctx) {
108 if (!isAnyDocsConnectorEnabled({ authorizedOverride: ctx.authorizedOverride })) {
109 return notAuthorized();
110 }
111 const connector = getConnector(ctx.dataDir, ctx.vaultId, ctx.connectorId);
112 if (!connector || connector.status === 'revoked') {
113 return { ok: false, status: 404, code: 'CONNECTOR_NOT_FOUND' };
114 }
115 if (connector.provider === 'google-drive') {
116 if (!isDocsGoogleOAuthEnabled({ authorizedOverride: ctx.authorizedOverride })) {
117 return notAuthorized();
118 }
119 if (action === 'list') return handleListDocsConnectorFiles(ctx);
120 if (action === 'import') return handleImportDocsConnectorFiles(ctx);
121 if (action === 'sync') return handleSyncDocsConnector(ctx);
122 if (action === 'revoke') return handleRevokeDocsConnector(ctx);
123 }
124 if (connector.provider === 'notion') {
125 if (!isDocsNotionHubKeyEnabled({ authorizedOverride: ctx.authorizedOverride })) {
126 return notAuthorized();
127 }
128 if (action === 'list') return handleListNotionConnectorFiles(ctx);
129 if (action === 'import') return handleImportNotionConnectorFiles(ctx);
130 if (action === 'sync') return handleSyncNotionConnector(ctx);
131 if (action === 'revoke') return handleRevokeNotionConnector(ctx);
132 }
133 return { ok: false, status: 400, code: 'PROVIDER_DENIED' };
134 }
135
136 export {
137 createProductionGoogleDriveClient,
138 createProductionNotionClient,
139 };
File History 1 commit
sha256:700fafdd1afa490919f9515d660ca6e75456bcd5bb67513abcd8757a634c01f6 docs: record AIP-b SD-21 land (KN #308) Human 9 days ago