doclific 0.1.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/.gitattributes +2 -0
- package/.prettierignore +5 -0
- package/.prettierrc +9 -0
- package/.vscode/settings.json +13 -0
- package/dist/bin/doclific.d.ts +3 -0
- package/dist/bin/doclific.d.ts.map +1 -0
- package/dist/bin/doclific.js +11 -0
- package/dist/core/codebase.js +31 -0
- package/dist/core/docs.js +75 -0
- package/dist/core/git.js +47 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +46 -0
- package/dist/server/router.d.ts +9 -0
- package/dist/server/router.d.ts.map +1 -0
- package/dist/server/router.js +55 -0
- package/frontend/README.md +73 -0
- package/frontend/components.json +24 -0
- package/frontend/eslint.config.js +23 -0
- package/frontend/index.html +25 -0
- package/frontend/package-lock.json +15754 -0
- package/frontend/package.json +122 -0
- package/frontend/public/logo.svg +1 -0
- package/frontend/src/App.tsx +21 -0
- package/frontend/src/components/app-sidebar.tsx +393 -0
- package/frontend/src/components/editor/editor-base-kit.tsx +43 -0
- package/frontend/src/components/editor/editor-kit.tsx +93 -0
- package/frontend/src/components/editor/plugins/align-base-kit.tsx +16 -0
- package/frontend/src/components/editor/plugins/align-kit.tsx +18 -0
- package/frontend/src/components/editor/plugins/autoformat-kit.tsx +236 -0
- package/frontend/src/components/editor/plugins/basic-blocks-base-kit.tsx +35 -0
- package/frontend/src/components/editor/plugins/basic-blocks-kit.tsx +88 -0
- package/frontend/src/components/editor/plugins/basic-marks-base-kit.tsx +27 -0
- package/frontend/src/components/editor/plugins/basic-marks-kit.tsx +41 -0
- package/frontend/src/components/editor/plugins/basic-nodes-kit.tsx +6 -0
- package/frontend/src/components/editor/plugins/block-menu-kit.tsx +14 -0
- package/frontend/src/components/editor/plugins/block-placeholder-kit.tsx +17 -0
- package/frontend/src/components/editor/plugins/block-selection-kit.tsx +32 -0
- package/frontend/src/components/editor/plugins/callout-base-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/callout-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/code-block-base-kit.tsx +23 -0
- package/frontend/src/components/editor/plugins/code-block-kit.tsx +26 -0
- package/frontend/src/components/editor/plugins/codebase-kit.tsx +23 -0
- package/frontend/src/components/editor/plugins/column-base-kit.tsx +11 -0
- package/frontend/src/components/editor/plugins/column-kit.tsx +10 -0
- package/frontend/src/components/editor/plugins/comment-base-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/comment-kit.tsx +97 -0
- package/frontend/src/components/editor/plugins/cursor-overlay-kit.tsx +13 -0
- package/frontend/src/components/editor/plugins/date-base-kit.tsx +5 -0
- package/frontend/src/components/editor/plugins/date-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/discussion-kit.tsx +148 -0
- package/frontend/src/components/editor/plugins/dnd-kit.tsx +28 -0
- package/frontend/src/components/editor/plugins/docx-kit.tsx +6 -0
- package/frontend/src/components/editor/plugins/emoji-kit.tsx +13 -0
- package/frontend/src/components/editor/plugins/excalidraw-kit.tsx +9 -0
- package/frontend/src/components/editor/plugins/exit-break-kit.tsx +12 -0
- package/frontend/src/components/editor/plugins/floating-toolbar-kit.tsx +19 -0
- package/frontend/src/components/editor/plugins/font-base-kit.tsx +20 -0
- package/frontend/src/components/editor/plugins/font-kit.tsx +29 -0
- package/frontend/src/components/editor/plugins/indent-base-kit.tsx +19 -0
- package/frontend/src/components/editor/plugins/indent-kit.tsx +22 -0
- package/frontend/src/components/editor/plugins/line-height-base-kit.tsx +14 -0
- package/frontend/src/components/editor/plugins/line-height-kit.tsx +16 -0
- package/frontend/src/components/editor/plugins/link-base-kit.tsx +5 -0
- package/frontend/src/components/editor/plugins/link-kit.tsx +15 -0
- package/frontend/src/components/editor/plugins/list-base-kit.tsx +23 -0
- package/frontend/src/components/editor/plugins/list-kit.tsx +26 -0
- package/frontend/src/components/editor/plugins/markdown-kit.tsx +46 -0
- package/frontend/src/components/editor/plugins/math-base-kit.tsx +11 -0
- package/frontend/src/components/editor/plugins/math-kit.tsx +13 -0
- package/frontend/src/components/editor/plugins/media-base-kit.tsx +31 -0
- package/frontend/src/components/editor/plugins/media-kit.tsx +43 -0
- package/frontend/src/components/editor/plugins/mention-base-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/mention-kit.tsx +15 -0
- package/frontend/src/components/editor/plugins/slash-kit.tsx +18 -0
- package/frontend/src/components/editor/plugins/suggestion-base-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/suggestion-kit.tsx +90 -0
- package/frontend/src/components/editor/plugins/table-base-kit.tsx +20 -0
- package/frontend/src/components/editor/plugins/table-kit.tsx +22 -0
- package/frontend/src/components/editor/plugins/toc-base-kit.tsx +5 -0
- package/frontend/src/components/editor/plugins/toc-kit.tsx +14 -0
- package/frontend/src/components/editor/plugins/toggle-base-kit.tsx +7 -0
- package/frontend/src/components/editor/plugins/toggle-kit.tsx +11 -0
- package/frontend/src/components/editor/transforms.ts +194 -0
- package/frontend/src/components/markdown-to-slate-demo.tsx +50 -0
- package/frontend/src/components/mode-toggle.tsx +15 -0
- package/frontend/src/components/theme-provider.tsx +73 -0
- package/frontend/src/components/ui/alert-dialog.tsx +155 -0
- package/frontend/src/components/ui/align-toolbar-button.tsx +84 -0
- package/frontend/src/components/ui/avatar.tsx +51 -0
- package/frontend/src/components/ui/block-context-menu.tsx +199 -0
- package/frontend/src/components/ui/block-discussion.tsx +365 -0
- package/frontend/src/components/ui/block-draggable.tsx +512 -0
- package/frontend/src/components/ui/block-list-static.tsx +80 -0
- package/frontend/src/components/ui/block-list.tsx +87 -0
- package/frontend/src/components/ui/block-selection.tsx +42 -0
- package/frontend/src/components/ui/block-suggestion.tsx +473 -0
- package/frontend/src/components/ui/blockquote-node-static.tsx +11 -0
- package/frontend/src/components/ui/blockquote-node.tsx +13 -0
- package/frontend/src/components/ui/button.tsx +62 -0
- package/frontend/src/components/ui/calendar.tsx +218 -0
- package/frontend/src/components/ui/callout-node-static.tsx +36 -0
- package/frontend/src/components/ui/callout-node.tsx +63 -0
- package/frontend/src/components/ui/caption.tsx +63 -0
- package/frontend/src/components/ui/checkbox.tsx +30 -0
- package/frontend/src/components/ui/code-block-node-static.tsx +35 -0
- package/frontend/src/components/ui/code-block-node.tsx +287 -0
- package/frontend/src/components/ui/code-node-static.tsx +15 -0
- package/frontend/src/components/ui/code-node.tsx +17 -0
- package/frontend/src/components/ui/codebase-snippet-node.tsx +237 -0
- package/frontend/src/components/ui/column-node-static.tsx +29 -0
- package/frontend/src/components/ui/column-node.tsx +317 -0
- package/frontend/src/components/ui/command.tsx +182 -0
- package/frontend/src/components/ui/comment-node-static.tsx +15 -0
- package/frontend/src/components/ui/comment-node.tsx +45 -0
- package/frontend/src/components/ui/comment-toolbar-button.tsx +24 -0
- package/frontend/src/components/ui/comment.tsx +618 -0
- package/frontend/src/components/ui/context-menu.tsx +250 -0
- package/frontend/src/components/ui/cursor-overlay.tsx +66 -0
- package/frontend/src/components/ui/date-node-static.tsx +45 -0
- package/frontend/src/components/ui/date-node.tsx +93 -0
- package/frontend/src/components/ui/dialog.tsx +143 -0
- package/frontend/src/components/ui/dropdown-menu.tsx +255 -0
- package/frontend/src/components/ui/dynamic-icon.tsx +12 -0
- package/frontend/src/components/ui/editor-static.tsx +53 -0
- package/frontend/src/components/ui/editor.tsx +130 -0
- package/frontend/src/components/ui/emoji-node.tsx +69 -0
- package/frontend/src/components/ui/emoji-toolbar-button.tsx +628 -0
- package/frontend/src/components/ui/equation-node-static.tsx +98 -0
- package/frontend/src/components/ui/equation-node.tsx +235 -0
- package/frontend/src/components/ui/equation-toolbar-button.tsx +25 -0
- package/frontend/src/components/ui/excalidraw-node.tsx +36 -0
- package/frontend/src/components/ui/export-toolbar-button.tsx +174 -0
- package/frontend/src/components/ui/file-selector.tsx +339 -0
- package/frontend/src/components/ui/floating-toolbar-buttons.tsx +73 -0
- package/frontend/src/components/ui/floating-toolbar.tsx +85 -0
- package/frontend/src/components/ui/font-color-toolbar-button.tsx +831 -0
- package/frontend/src/components/ui/font-size-toolbar-button.tsx +152 -0
- package/frontend/src/components/ui/heading-node-static.tsx +68 -0
- package/frontend/src/components/ui/heading-node.tsx +58 -0
- package/frontend/src/components/ui/highlight-node-static.tsx +11 -0
- package/frontend/src/components/ui/highlight-node.tsx +13 -0
- package/frontend/src/components/ui/history-toolbar-button.tsx +50 -0
- package/frontend/src/components/ui/hr-node-static.tsx +20 -0
- package/frontend/src/components/ui/hr-node.tsx +33 -0
- package/frontend/src/components/ui/import-toolbar-button.tsx +97 -0
- package/frontend/src/components/ui/indent-toolbar-button.tsx +30 -0
- package/frontend/src/components/ui/inline-combobox.tsx +414 -0
- package/frontend/src/components/ui/input.tsx +21 -0
- package/frontend/src/components/ui/insert-toolbar-button.tsx +254 -0
- package/frontend/src/components/ui/kbd-node-static.tsx +15 -0
- package/frontend/src/components/ui/kbd-node.tsx +17 -0
- package/frontend/src/components/ui/layout-header.tsx +35 -0
- package/frontend/src/components/ui/line-height-toolbar-button.tsx +68 -0
- package/frontend/src/components/ui/link-node-static.tsx +21 -0
- package/frontend/src/components/ui/link-node.tsx +39 -0
- package/frontend/src/components/ui/link-toolbar-button.tsx +22 -0
- package/frontend/src/components/ui/link-toolbar.tsx +206 -0
- package/frontend/src/components/ui/list-toolbar-button.tsx +204 -0
- package/frontend/src/components/ui/mark-toolbar-button.tsx +19 -0
- package/frontend/src/components/ui/media-audio-node-static.tsx +17 -0
- package/frontend/src/components/ui/media-audio-node.tsx +39 -0
- package/frontend/src/components/ui/media-embed-node.tsx +136 -0
- package/frontend/src/components/ui/media-file-node-static.tsx +29 -0
- package/frontend/src/components/ui/media-file-node.tsx +47 -0
- package/frontend/src/components/ui/media-image-node-static.tsx +39 -0
- package/frontend/src/components/ui/media-image-node.tsx +80 -0
- package/frontend/src/components/ui/media-placeholder-node.tsx +249 -0
- package/frontend/src/components/ui/media-preview-dialog.tsx +152 -0
- package/frontend/src/components/ui/media-toolbar-button.tsx +225 -0
- package/frontend/src/components/ui/media-toolbar.tsx +115 -0
- package/frontend/src/components/ui/media-upload-toast.tsx +66 -0
- package/frontend/src/components/ui/media-video-node-static.tsx +30 -0
- package/frontend/src/components/ui/media-video-node.tsx +121 -0
- package/frontend/src/components/ui/mention-node-static.tsx +36 -0
- package/frontend/src/components/ui/mention-node.tsx +194 -0
- package/frontend/src/components/ui/mode-toolbar-button.tsx +123 -0
- package/frontend/src/components/ui/more-toolbar-button.tsx +80 -0
- package/frontend/src/components/ui/paragraph-node-static.tsx +13 -0
- package/frontend/src/components/ui/paragraph-node.tsx +15 -0
- package/frontend/src/components/ui/popover.tsx +46 -0
- package/frontend/src/components/ui/resize-handle.tsx +87 -0
- package/frontend/src/components/ui/separator.tsx +28 -0
- package/frontend/src/components/ui/sheet.tsx +139 -0
- package/frontend/src/components/ui/sidebar.tsx +726 -0
- package/frontend/src/components/ui/skeleton.tsx +13 -0
- package/frontend/src/components/ui/slash-node.tsx +233 -0
- package/frontend/src/components/ui/sonner.tsx +38 -0
- package/frontend/src/components/ui/suggestion-node-static.tsx +35 -0
- package/frontend/src/components/ui/suggestion-node.tsx +162 -0
- package/frontend/src/components/ui/suggestion-toolbar-button.tsx +25 -0
- package/frontend/src/components/ui/table-icons.tsx +862 -0
- package/frontend/src/components/ui/table-node-static.tsx +98 -0
- package/frontend/src/components/ui/table-node.tsx +656 -0
- package/frontend/src/components/ui/table-toolbar-button.tsx +264 -0
- package/frontend/src/components/ui/toc-node-static.tsx +92 -0
- package/frontend/src/components/ui/toc-node.tsx +55 -0
- package/frontend/src/components/ui/toggle-node-static.tsx +18 -0
- package/frontend/src/components/ui/toggle-node.tsx +36 -0
- package/frontend/src/components/ui/toggle-toolbar-button.tsx +22 -0
- package/frontend/src/components/ui/toolbar.tsx +387 -0
- package/frontend/src/components/ui/tooltip.tsx +59 -0
- package/frontend/src/components/ui/turn-into-toolbar-button.tsx +188 -0
- package/frontend/src/hooks/use-debounce.ts +18 -0
- package/frontend/src/hooks/use-is-touch-device.ts +24 -0
- package/frontend/src/hooks/use-mobile.ts +19 -0
- package/frontend/src/hooks/use-mounted.ts +11 -0
- package/frontend/src/hooks/use-upload-file.ts +128 -0
- package/frontend/src/index.css +128 -0
- package/frontend/src/layout.tsx +42 -0
- package/frontend/src/lib/markdown-joiner-transform.ts +239 -0
- package/frontend/src/lib/orpc.ts +13 -0
- package/frontend/src/lib/uploadthing.ts +19 -0
- package/frontend/src/lib/utils.ts +6 -0
- package/frontend/src/main.tsx +13 -0
- package/frontend/src/pages/editor.tsx +44 -0
- package/frontend/src/types/docs.d.ts +6 -0
- package/frontend/src/types/global.d.ts +9 -0
- package/frontend/src/types/router.d.ts +4 -0
- package/frontend/tsconfig.app.json +33 -0
- package/frontend/tsconfig.json +10 -0
- package/frontend/tsconfig.node.json +26 -0
- package/frontend/vite.config.ts +14 -0
- package/package.json +30 -0
- package/src/bin/doclific.ts +17 -0
- package/src/core/codebase.ts +39 -0
- package/src/core/docs.ts +90 -0
- package/src/core/git.ts +48 -0
- package/src/server/index.ts +55 -0
- package/src/server/router.ts +65 -0
- package/tsconfig.json +15 -0
package/.gitattributes
ADDED
package/.prettierignore
ADDED
package/.prettierrc
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"editor.formatOnSave": true,
|
|
3
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
4
|
+
"[typescript]": {
|
|
5
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
6
|
+
},
|
|
7
|
+
"[javascript]": {
|
|
8
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
9
|
+
},
|
|
10
|
+
"[json]": {
|
|
11
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doclific.d.ts","sourceRoot":"","sources":["../../src/bin/doclific.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import { startServer } from '../server/index.js';
|
|
4
|
+
const port = process.argv.find((arg) => arg.startsWith('-p=') || arg.startsWith('--port='))?.split('=')[1] ||
|
|
5
|
+
6767;
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
console.log('Doclific CLI running in directory:', cwd);
|
|
8
|
+
startServer(Number(port));
|
|
9
|
+
// Optional: open browser automatically
|
|
10
|
+
const open = process.platform === 'win32' ? 'start' : process.platform === 'darwin' ? 'open' : 'xdg-open';
|
|
11
|
+
spawn(open, [`http://localhost:${port}`]);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
/**
|
|
4
|
+
* Get all contents of a folder given a filePath.
|
|
5
|
+
* @param filePath - The relative path to the folder
|
|
6
|
+
*/
|
|
7
|
+
export const getFolderContents = async (filePath) => {
|
|
8
|
+
const currentDir = process.cwd();
|
|
9
|
+
let fullPath = '';
|
|
10
|
+
if (filePath !== '') {
|
|
11
|
+
fullPath = path.join(currentDir, filePath);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
fullPath = currentDir;
|
|
15
|
+
}
|
|
16
|
+
const entries = await fs.readdir(fullPath, { withFileTypes: true });
|
|
17
|
+
const nodes = [];
|
|
18
|
+
for (const entry of entries) {
|
|
19
|
+
nodes.push({
|
|
20
|
+
path: path.join(filePath, entry.name),
|
|
21
|
+
name: entry.name,
|
|
22
|
+
type: entry.isDirectory() ? 'directory' : 'file',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return nodes;
|
|
26
|
+
};
|
|
27
|
+
export const getFileContents = async (filePath) => {
|
|
28
|
+
const currentDir = process.cwd();
|
|
29
|
+
const fullPath = path.join(currentDir, filePath);
|
|
30
|
+
return fs.readFile(fullPath, 'utf8');
|
|
31
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const scanDirectory = async (dirPath) => {
|
|
4
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
5
|
+
const folders = [];
|
|
6
|
+
for (const entry of entries) {
|
|
7
|
+
if (entry.isDirectory()) {
|
|
8
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
9
|
+
const children = await scanDirectory(fullPath);
|
|
10
|
+
let config = {
|
|
11
|
+
title: entry.name,
|
|
12
|
+
icon: undefined,
|
|
13
|
+
};
|
|
14
|
+
// get the config.json file
|
|
15
|
+
const configPath = path.join(fullPath, 'config.json');
|
|
16
|
+
try {
|
|
17
|
+
const configFile = await fs.readFile(configPath, 'utf8');
|
|
18
|
+
config = JSON.parse(configFile);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
throw new Error(`Config file not found for ${entry.name}`);
|
|
22
|
+
}
|
|
23
|
+
folders.push({
|
|
24
|
+
name: entry.name,
|
|
25
|
+
title: config.title,
|
|
26
|
+
icon: config.icon,
|
|
27
|
+
children,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return folders;
|
|
32
|
+
};
|
|
33
|
+
export const getDocs = async () => {
|
|
34
|
+
const docsFolder = path.join(process.cwd(), 'doclific');
|
|
35
|
+
try {
|
|
36
|
+
await fs.access(docsFolder);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
return scanDirectory(docsFolder);
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* This function will return the content of the .mdx file in the directory with the given filePath.
|
|
45
|
+
* @param filePath - The path to the file
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
export const getDoc = async (filePath) => {
|
|
49
|
+
const currentDir = process.cwd();
|
|
50
|
+
const fullPath = path.join(currentDir, 'doclific', filePath);
|
|
51
|
+
try {
|
|
52
|
+
return fs.readFile(path.join(fullPath, 'content.mdx'), 'utf8');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
export const updateDoc = async (filePath, content) => {
|
|
59
|
+
const currentDir = process.cwd();
|
|
60
|
+
const fullPath = path.join(currentDir, 'doclific', filePath);
|
|
61
|
+
await fs.writeFile(path.join(fullPath, 'content.mdx'), content);
|
|
62
|
+
};
|
|
63
|
+
export const createDoc = async (filePath, title, icon) => {
|
|
64
|
+
const currentDir = process.cwd();
|
|
65
|
+
const fullPath = path.join(currentDir, 'doclific', filePath);
|
|
66
|
+
const newFolderName = crypto.randomUUID();
|
|
67
|
+
const newFolderPath = path.join(fullPath, newFolderName);
|
|
68
|
+
await fs.mkdir(newFolderPath, { recursive: true });
|
|
69
|
+
// create content.mdx file
|
|
70
|
+
await fs.writeFile(path.join(newFolderPath, 'content.mdx'), '# Hello World');
|
|
71
|
+
// create config.json file
|
|
72
|
+
await fs.writeFile(path.join(newFolderPath, 'config.json'), JSON.stringify({ title, icon }, null, 2));
|
|
73
|
+
// return the new folder path
|
|
74
|
+
return newFolderPath;
|
|
75
|
+
};
|
package/dist/core/git.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import util from 'util';
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
const execAsync = util.promisify(exec);
|
|
4
|
+
export const getGitRepositoryName = async () => {
|
|
5
|
+
try {
|
|
6
|
+
const GET_REPO_NAME_COMMAND = `git config --get remote.origin.url | sed -E "s|.*/(.+)\\.git|\\1|"`;
|
|
7
|
+
const repoName = await execAsync(GET_REPO_NAME_COMMAND);
|
|
8
|
+
return repoName.stdout.toString().trim();
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
console.error(error);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const getGitRepositoryBranch = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const GET_REPO_BRANCH_COMMAND = `git rev-parse --abbrev-ref HEAD`;
|
|
18
|
+
const repoBranch = await execAsync(GET_REPO_BRANCH_COMMAND);
|
|
19
|
+
return repoBranch.stdout.toString().trim();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error(error);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export const getGitUser = async () => {
|
|
27
|
+
try {
|
|
28
|
+
const GET_USER_COMMAND = `git config user.name`;
|
|
29
|
+
const user = await execAsync(GET_USER_COMMAND);
|
|
30
|
+
return user.stdout.toString().trim();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(error);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export const getGitUserEmail = async () => {
|
|
38
|
+
try {
|
|
39
|
+
const GET_USER_EMAIL_COMMAND = `git config user.email`;
|
|
40
|
+
const userEmail = await execAsync(GET_USER_EMAIL_COMMAND);
|
|
41
|
+
return userEmail.stdout.toString().trim();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.error(error);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAa,QAyB9C"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import cors from 'cors';
|
|
3
|
+
import { RPCHandler } from '@orpc/server/node';
|
|
4
|
+
import { onError } from '@orpc/server';
|
|
5
|
+
import { router } from './router.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const frontendDist = path.join(__dirname, '../../frontend/dist');
|
|
12
|
+
export function startServer(port = 6767) {
|
|
13
|
+
const app = express();
|
|
14
|
+
app.use(cors());
|
|
15
|
+
const handler = new RPCHandler(router, {
|
|
16
|
+
interceptors: [
|
|
17
|
+
onError((error) => {
|
|
18
|
+
console.error(error);
|
|
19
|
+
}),
|
|
20
|
+
],
|
|
21
|
+
});
|
|
22
|
+
app.use('/rpc{/*path}', async (req, res, next) => {
|
|
23
|
+
const { matched } = await handler.handle(req, res, {
|
|
24
|
+
prefix: '/rpc',
|
|
25
|
+
context: {},
|
|
26
|
+
});
|
|
27
|
+
if (matched)
|
|
28
|
+
return;
|
|
29
|
+
next();
|
|
30
|
+
});
|
|
31
|
+
// serve static files in frontend/dist
|
|
32
|
+
app.use((req, res, next) => {
|
|
33
|
+
if (req.url === '/') {
|
|
34
|
+
const html = fs.readFileSync(path.join(frontendDist, 'index.html'), 'utf8');
|
|
35
|
+
res.send(html.replace(': BACKEND_PORT', `: ${port.toString()}`));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
express.static(frontendDist)(req, res, next);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
app.get('/{*splat}', (req, res) => {
|
|
42
|
+
const html = fs.readFileSync(path.join(frontendDist, 'index.html'), 'utf8');
|
|
43
|
+
res.send(html.replace(': BACKEND_PORT', `: ${port.toString()}`));
|
|
44
|
+
});
|
|
45
|
+
app.listen(port, () => console.log(`Access your documentation here: http://localhost:${port}`));
|
|
46
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const router: {
|
|
2
|
+
ping: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<string, string>, Record<never, never>, Record<never, never>>;
|
|
3
|
+
pong: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<string, string>, Record<never, never>, Record<never, never>>;
|
|
4
|
+
nested: {
|
|
5
|
+
ping: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<string, string>, Record<never, never>, Record<never, never>>;
|
|
6
|
+
pong: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<string, string>, Record<never, never>, Record<never, never>>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM;;;;;;;CAIlB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { os } from '@orpc/server';
|
|
2
|
+
import { getGitRepositoryBranch, getGitRepositoryName, getGitUser, getGitUserEmail, } from '../core/git.js';
|
|
3
|
+
import { createDoc, getDoc, getDocs, updateDoc } from '../core/docs.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { getFileContents, getFolderContents } from '../core/codebase.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
export const router = {
|
|
8
|
+
git: {
|
|
9
|
+
getRepoInfo: os.handler(async () => {
|
|
10
|
+
return {
|
|
11
|
+
repositoryName: await getGitRepositoryName(),
|
|
12
|
+
repositoryBranch: await getGitRepositoryBranch(),
|
|
13
|
+
user: await getGitUser(),
|
|
14
|
+
userEmail: await getGitUserEmail(),
|
|
15
|
+
};
|
|
16
|
+
}),
|
|
17
|
+
},
|
|
18
|
+
docs: {
|
|
19
|
+
getDocs: os.handler(async () => {
|
|
20
|
+
return await getDocs();
|
|
21
|
+
}),
|
|
22
|
+
getDoc: os.input(z.object({ filePath: z.string() })).handler(async ({ input }) => {
|
|
23
|
+
const { filePath } = input;
|
|
24
|
+
return await getDoc(filePath);
|
|
25
|
+
}),
|
|
26
|
+
updateDoc: os
|
|
27
|
+
.input(z.object({ filePath: z.string(), content: z.string() }))
|
|
28
|
+
.handler(async ({ input }) => {
|
|
29
|
+
const { filePath, content } = input;
|
|
30
|
+
return await updateDoc(filePath, content);
|
|
31
|
+
}),
|
|
32
|
+
createDoc: os
|
|
33
|
+
.input(z.object({ filePath: z.string(), title: z.string(), icon: z.string().optional() }))
|
|
34
|
+
.handler(async ({ input }) => {
|
|
35
|
+
const { filePath, title, icon } = input;
|
|
36
|
+
return await createDoc(filePath, title, icon);
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
codebase: {
|
|
40
|
+
getFolderContents: os
|
|
41
|
+
.input(z.object({ filePath: z.string() }))
|
|
42
|
+
.handler(async ({ input }) => {
|
|
43
|
+
const { filePath } = input;
|
|
44
|
+
return await getFolderContents(filePath);
|
|
45
|
+
}),
|
|
46
|
+
getFileContents: os.input(z.object({ filePath: z.string() })).handler(async ({ input }) => {
|
|
47
|
+
const { filePath } = input;
|
|
48
|
+
const currentDir = process.cwd();
|
|
49
|
+
return {
|
|
50
|
+
contents: await getFileContents(filePath),
|
|
51
|
+
fullPath: path.join(currentDir, '..', filePath),
|
|
52
|
+
};
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# React + TypeScript + Vite
|
|
2
|
+
|
|
3
|
+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
4
|
+
|
|
5
|
+
Currently, two official plugins are available:
|
|
6
|
+
|
|
7
|
+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
|
|
8
|
+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
|
9
|
+
|
|
10
|
+
## React Compiler
|
|
11
|
+
|
|
12
|
+
The React Compiler is currently not compatible with SWC. See [this issue](https://github.com/vitejs/vite-plugin-react/issues/428) for tracking the progress.
|
|
13
|
+
|
|
14
|
+
## Expanding the ESLint configuration
|
|
15
|
+
|
|
16
|
+
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
export default defineConfig([
|
|
20
|
+
globalIgnores(['dist']),
|
|
21
|
+
{
|
|
22
|
+
files: ['**/*.{ts,tsx}'],
|
|
23
|
+
extends: [
|
|
24
|
+
// Other configs...
|
|
25
|
+
|
|
26
|
+
// Remove tseslint.configs.recommended and replace with this
|
|
27
|
+
tseslint.configs.recommendedTypeChecked,
|
|
28
|
+
// Alternatively, use this for stricter rules
|
|
29
|
+
tseslint.configs.strictTypeChecked,
|
|
30
|
+
// Optionally, add this for stylistic rules
|
|
31
|
+
tseslint.configs.stylisticTypeChecked,
|
|
32
|
+
|
|
33
|
+
// Other configs...
|
|
34
|
+
],
|
|
35
|
+
languageOptions: {
|
|
36
|
+
parserOptions: {
|
|
37
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
38
|
+
tsconfigRootDir: import.meta.dirname,
|
|
39
|
+
},
|
|
40
|
+
// other options...
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
])
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// eslint.config.js
|
|
50
|
+
import reactX from 'eslint-plugin-react-x'
|
|
51
|
+
import reactDom from 'eslint-plugin-react-dom'
|
|
52
|
+
|
|
53
|
+
export default defineConfig([
|
|
54
|
+
globalIgnores(['dist']),
|
|
55
|
+
{
|
|
56
|
+
files: ['**/*.{ts,tsx}'],
|
|
57
|
+
extends: [
|
|
58
|
+
// Other configs...
|
|
59
|
+
// Enable lint rules for React
|
|
60
|
+
reactX.configs['recommended-typescript'],
|
|
61
|
+
// Enable lint rules for React DOM
|
|
62
|
+
reactDom.configs.recommended,
|
|
63
|
+
],
|
|
64
|
+
languageOptions: {
|
|
65
|
+
parserOptions: {
|
|
66
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
67
|
+
tsconfigRootDir: import.meta.dirname,
|
|
68
|
+
},
|
|
69
|
+
// other options...
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
])
|
|
73
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "src/index.css",
|
|
9
|
+
"baseColor": "zinc",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"iconLibrary": "lucide",
|
|
14
|
+
"aliases": {
|
|
15
|
+
"components": "@/components",
|
|
16
|
+
"utils": "@/lib/utils",
|
|
17
|
+
"ui": "@/components/ui",
|
|
18
|
+
"lib": "@/lib",
|
|
19
|
+
"hooks": "@/hooks"
|
|
20
|
+
},
|
|
21
|
+
"registries": {
|
|
22
|
+
"@plate": "https://platejs.org/r/{name}.json"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import globals from 'globals'
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
+
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
+
import tseslint from 'typescript-eslint'
|
|
6
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
7
|
+
|
|
8
|
+
export default defineConfig([
|
|
9
|
+
globalIgnores(['dist']),
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.{ts,tsx}'],
|
|
12
|
+
extends: [
|
|
13
|
+
js.configs.recommended,
|
|
14
|
+
tseslint.configs.recommended,
|
|
15
|
+
reactHooks.configs.flat.recommended,
|
|
16
|
+
reactRefresh.configs.vite,
|
|
17
|
+
],
|
|
18
|
+
languageOptions: {
|
|
19
|
+
ecmaVersion: 2020,
|
|
20
|
+
globals: globals.browser,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
])
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Doclific</title>
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
10
|
+
<link
|
|
11
|
+
href="https://fonts.googleapis.com/css2?family=Google+Sans+Code:ital,wght@0,300..800;1,300..800&display=swap"
|
|
12
|
+
rel="stylesheet"
|
|
13
|
+
/>
|
|
14
|
+
<script>
|
|
15
|
+
const BACKEND_PORT = 6767;
|
|
16
|
+
window.env = {
|
|
17
|
+
PORT: BACKEND_PORT,
|
|
18
|
+
};
|
|
19
|
+
</script>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<div id="root"></div>
|
|
23
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|