public
anord
read
Ledger
Why work hard when you can work easier?
Languages
Repository composition by tracked source files.
TypeScript
86%
CSS
10%
SQL
3%
Shell
1%
HTML
0%
import { Router } from "express";
import { z } from "zod";
import { requireAdmin, requireEditor } from "../middleware/auth.js";
import {
importGitHubDocument,
importGoogleDoc,
importMarkdownDocuments,
listImportJobs,
listIntegrations,
previewGitHubImport,
previewGoogleDocImport,
previewMarkdownImports,
upsertIntegration
} from "../../services/integrations.js";
const integrationSchema = z.object({
name: z.string().min(2),
config: z.record(z.any()),
isEnabled: z.boolean()
});
const importTargetSchema = z.object({
spaceId: z.string().uuid(),
visibility: z.enum(["public", "internal", "restricted"]),
state: z.enum(["draft", "published"]),
parentPageId: z.string().uuid().nullable().optional(),
allowedRoleKeys: z.array(z.enum(["owner", "admin", "editor", "viewer", "public"])).optional(),
allowedGroupIds: z.array(z.string().uuid()).optional()
});
const markdownPreviewSchema = z.object({
files: z.array(
z.object({
fileName: z.string().min(1),
content: z.string().min(1)
})
).min(1)
});
const githubSchema = z.object({
repo: z.string().min(3),
branch: z.string().min(1),
path: z.string().min(1)
});
const googleDocsSchema = z.object({
documentId: z.string().min(10)
});
export const integrationsRouter = Router();
integrationsRouter.get("/", requireEditor, async (_req, res) => {
return res.json({ integrations: await listIntegrations() });
});
integrationsRouter.put("/:provider", requireAdmin, async (req, res) => {
const provider = z.enum(["github", "google_docs", "markdown_import"]).parse(req.params.provider);
const input = integrationSchema.parse(req.body);
const integration = await upsertIntegration(provider, input);
return res.json({ integration });
});
integrationsRouter.get("/import-jobs", requireEditor, async (_req, res) => {
return res.json({ jobs: await listImportJobs() });
});
integrationsRouter.post("/markdown/preview", requireEditor, async (req, res) => {
const input = markdownPreviewSchema.parse(req.body);
return res.json({ documents: previewMarkdownImports(input.files) });
});
integrationsRouter.post("/markdown/import", requireEditor, async (req, res) => {
const input = z.object({
files: markdownPreviewSchema.shape.files,
target: importTargetSchema
}).parse(req.body);
const result = await importMarkdownDocuments(input.files, input.target, req.user!.id);
return res.status(201).json(result);
});
integrationsRouter.post("/github/preview", requireEditor, async (req, res) => {
const input = githubSchema.parse(req.body);
const document = await previewGitHubImport(input.repo, input.branch, input.path);
return res.json({ document });
});
integrationsRouter.post("/github/import", requireEditor, async (req, res) => {
const input = z.object({
repo: githubSchema.shape.repo,
branch: githubSchema.shape.branch,
path: githubSchema.shape.path,
target: importTargetSchema
}).parse(req.body);
const result = await importGitHubDocument(input.repo, input.branch, input.path, input.target, req.user!.id);
return res.status(201).json(result);
});
integrationsRouter.post("/google-docs/preview", requireEditor, async (req, res) => {
const input = googleDocsSchema.parse(req.body);
const document = await previewGoogleDocImport(input.documentId);
return res.json({ document });
});
integrationsRouter.post("/google-docs/import", requireEditor, async (req, res) => {
const input = z.object({
documentId: googleDocsSchema.shape.documentId,
target: importTargetSchema
}).parse(req.body);
const result = await importGoogleDoc(input.documentId, input.target, req.user!.id);
return res.status(201).json(result);
});