NobGit
public anord read

Ledger

Why work hard when you can work easier?

Languages

Repository composition by tracked source files.

TypeScript
TypeScript 86% CSS 10% SQL 3% Shell 1% HTML 0%
Create file Wiki Documentation
Clone
https://nobgit.com/orgs/anord/ledger.git
ssh://[email protected]:2222/orgs/anord/ledger.git
integrations.ts
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);
});