Skip to content

Commit f03b6b0

Browse files
authored
make codepod (cli) support /path/to/repo; publish codepod to npm (#565)
1 parent efce208 commit f03b6b0

File tree

15 files changed

+97
-48
lines changed

15 files changed

+97
-48
lines changed

apps/api/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
dist/
22
conns/conn-*.json
3-
prisma/dev.db
3+
prisma/dev.db
4+
example-repo/
5+
public/

apps/api/.npmignore

Whitespace-only changes.

apps/api/package.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
{
2-
"name": "api",
3-
"version": "1.0.0",
2+
"name": "codepod",
3+
"version": "0.0.4",
44
"license": "MIT",
55
"scripts": {
66
"build": "tsc",
77
"start": "node build/run.js",
88
"dev": "ts-node-dev src/run.ts",
99
"test": "jest --config jest.config.js"
1010
},
11+
"bin": {
12+
"codepod": "./build/bin.js"
13+
},
1114
"dependencies": {
12-
"@codepod/yjs": "workspace:^",
15+
"@codepod/ui": "workspace:^",
16+
"commander": "^11.0.0",
1317
"cors": "^2.8.5",
1418
"express": "^4.18.2",
1519
"jest": "^29.0.3",
20+
"lib0": "^0.2.83",
1621
"lodash": "^4.17.21",
1722
"ws": "^8.2.3",
23+
"y-protocols": "^1.0.5",
1824
"yjs": "^13.6.7"
1925
},
2026
"devDependencies": {

apps/api/src/bin.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env node
2+
3+
import { program } from "commander";
4+
import { startServer } from "./server";
5+
6+
// This is a binary executable to run the server.
7+
8+
// First, parse the command line arguments.
9+
// CMD: codepod /path/to/repo
10+
11+
program
12+
.version("0.0.1")
13+
.arguments("<repoPath>")
14+
.action(function (repoPath) {
15+
console.log("repoPath", repoPath);
16+
// start the server
17+
startServer({ port: 4001, blobDir: repoPath });
18+
});
19+
20+
program.parse(process.argv);

apps/api/src/run.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
import { startServer } from "./server";
22

3-
startServer({ port: 4000 });
3+
const blobDir = `${process.cwd()}/example-repo`;
4+
console.log("blobDir", blobDir);
5+
6+
startServer({ port: 4000, blobDir });

apps/api/src/server.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,32 @@ import express from "express";
22
import http from "http";
33
import { WebSocketServer } from "ws";
44

5-
import { createSetupWSConnection } from "@codepod/yjs";
5+
import { createSetupWSConnection } from "./yjs/yjs-setupWS";
66
import { bindState, writeState } from "./yjs-blob";
77

88
import cors from "cors";
99

10-
export async function startServer({ port }) {
10+
export async function startServer({ port, blobDir }) {
11+
console.log("starting server ..");
1112
const app = express();
1213
app.use(express.json({ limit: "20mb" }));
1314
// support cors
1415
app.use(cors());
1516
// serve static files generated from UI
16-
app.use(express.static("../../packages/ui/dist"));
17+
const path = `${__dirname}/../public`;
18+
console.log("html path: ", path);
19+
app.use(express.static(path));
1720

1821
const http_server = http.createServer(app);
1922

2023
// Yjs websocket
2124
const wss = new WebSocketServer({ noServer: true });
2225

2326
wss.on("connection", (...args) =>
24-
createSetupWSConnection(bindState, writeState)(...args)
27+
createSetupWSConnection(
28+
(doc, repoId) => bindState(doc, repoId, blobDir),
29+
writeState
30+
)(...args)
2531
);
2632

2733
http_server.on("upgrade", async (request, socket, head) => {

apps/api/src/yjs-blob.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,7 @@ function getDebouncedCallback(key) {
5050
return debounceRegistry.get(key);
5151
}
5252

53-
// FIXME hard-coded path.
54-
const blobDir = "/tmp/example-repo";
55-
56-
async function handleSaveBlob({ repoId, yDocBlob }) {
53+
async function handleSaveBlob({ repoId, yDocBlob, blobDir }) {
5754
console.log("save blob", repoId, yDocBlob.length);
5855
// create the yjs-blob folder if not exists
5956
if (!fs.existsSync(blobDir)) {
@@ -67,7 +64,7 @@ async function handleSaveBlob({ repoId, yDocBlob }) {
6764
* This function is called when setting up the WS connection, after the loadFromCodePod step.
6865
* TODO need to make sure this is only called once per repo, regardless of how many users are connected later.
6966
*/
70-
function setupObserversToDB(ydoc: Y.Doc, repoId: string) {
67+
function setupObserversToDB(ydoc: Y.Doc, repoId: string, blobDir: string) {
7168
console.log("setupObserversToDB for repo", repoId);
7269
// just observe and save the entire doc
7370
function observer(_, transaction) {
@@ -82,7 +79,7 @@ function setupObserversToDB(ydoc: Y.Doc, repoId: string) {
8279
// FIXME it may be too expensive to update the entire doc.
8380
// FIXME history is discarded
8481
const update = Y.encodeStateAsUpdate(ydoc);
85-
handleSaveBlob({ repoId, yDocBlob: Buffer.from(update) });
82+
handleSaveBlob({ repoId, yDocBlob: Buffer.from(update), blobDir });
8683
});
8784
}
8885
const rootMap = ydoc.getMap("rootMap");
@@ -101,7 +98,7 @@ function setupObserversToDB(ydoc: Y.Doc, repoId: string) {
10198
/**
10299
* This function is called when setting up the WS connection, as a first step.
103100
*/
104-
async function loadFromFS(ydoc: Y.Doc, repoId: string) {
101+
async function loadFromFS(ydoc: Y.Doc, repoId: string, blobDir: string) {
105102
// load from the database and write to the ydoc
106103
console.log("=== loadFromFS");
107104
// read the blob from file system
@@ -124,11 +121,11 @@ async function loadFromFS(ydoc: Y.Doc, repoId: string) {
124121
}
125122
}
126123

127-
export async function bindState(doc: Y.Doc, repoId: string) {
124+
export async function bindState(doc: Y.Doc, repoId: string, blobDir: string) {
128125
// Load persisted document state from the database.
129-
await loadFromFS(doc, repoId);
126+
await loadFromFS(doc, repoId, blobDir);
130127
// Observe changes and write to the database.
131-
setupObserversToDB(doc, repoId);
128+
setupObserversToDB(doc, repoId, blobDir);
132129
// setupObserversToRuntime(doc, repoId);
133130
// reset runtime status
134131
// clear runtimeMap status/commands but keep the ID

packages/yjs/src/yjs-setupWS.ts renamed to apps/api/src/yjs/yjs-setupWS.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as syncProtocol from "y-protocols/sync";
66

77
import { encoding, decoding, map } from "lib0";
88

9-
let writeState = () => {
9+
let writeState: () => any = () => {
1010
throw new Error("writeState not set");
1111
};
1212
let bindState = async (doc: Y.Doc, repoId: string) => {
@@ -275,7 +275,10 @@ const pingTimeout = 30000;
275275
* @param {any} req
276276
* @param {any} opts
277277
*/
278-
export const createSetupWSConnection = (_bindState, _writeState) => {
278+
export const createSetupWSConnection = (
279+
_bindState: (doc: Y.Doc, repoId: string) => any,
280+
_writeState: () => any
281+
) => {
279282
// set the writeState and bindState functions
280283
writeState = _writeState;
281284
bindState = _bindState;

apps/spawner/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "spawner",
2+
"name": "@codepod/spawner",
33
"version": "1.0.0",
44
"license": "MIT",
55
"scripts": {

apps/ui/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
2-
"name": "ui",
3-
"private": true,
2+
"name": "@codepod/ui",
43
"version": "0.0.0",
54
"type": "module",
65
"main": "src/index.tsx",

0 commit comments

Comments
 (0)