Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge CSV2 Branch into lix-integration #3152

Merged
merged 62 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
dc195b4
stash merge
NilsJacobsen Sep 5, 2024
ace6c76
feat: inital lix functions
NilsJacobsen Sep 10, 2024
30fa3a0
feat: add scenario/project launcher
NilsJacobsen Sep 10, 2024
b7e87e6
feat: add drawer that gets selection information
NilsJacobsen Sep 11, 2024
2c95aeb
feat: add drawer
NilsJacobsen Sep 11, 2024
591f3fd
fix: drawer and only show cell history
NilsJacobsen Sep 12, 2024
6dff685
feat: add basic importing of csvs
NilsJacobsen Sep 13, 2024
65b28c9
Merge remote-tracking branch 'origin/lix-integration' into csv-app2
NilsJacobsen Sep 13, 2024
ef9a251
chore: fix lockfile
NilsJacobsen Sep 13, 2024
9f00d90
feat: add metadata configuration & pass it in plugin
NilsJacobsen Sep 13, 2024
b34abe4
chore: remove log
NilsJacobsen Sep 13, 2024
a31b263
feat: add download csv + cleanup
NilsJacobsen Sep 13, 2024
daa8ccf
feat: update dashboard view
NilsJacobsen Sep 13, 2024
c3b21a7
feat: open demo simple
NilsJacobsen Sep 13, 2024
0bacfc4
feat: put csvs in public folder
NilsJacobsen Sep 13, 2024
d5773dd
feat: log errors
NilsJacobsen Sep 16, 2024
50f2ddf
feat: log error
NilsJacobsen Sep 16, 2024
a0c09d4
feat: polyfill opfs writable for safari
NilsJacobsen Sep 17, 2024
155b4ac
fix: show author modal
NilsJacobsen Sep 17, 2024
a3680f9
chore: cleanup
NilsJacobsen Sep 17, 2024
866d402
feat: add history tab and view
NilsJacobsen Sep 18, 2024
2d120dd
Merge pull request #3130 from opral/csv-app2-history
NilsJacobsen Sep 18, 2024
42993f1
chore: fix nav padding
NilsJacobsen Sep 18, 2024
83537a5
feat: add link to lix
NilsJacobsen Sep 18, 2024
b6b5c3c
feat: add download .lix
NilsJacobsen Sep 23, 2024
5bafec1
feat: add better cap-table demo data
NilsJacobsen Sep 24, 2024
998fa16
adds a test server - fixes csv plugin
martin-lysk Sep 24, 2024
f047371
plugin applyChange, detect conflict for json file added
martin-lysk Sep 24, 2024
dc7c8f8
handle multiple files in merge function
martin-lysk Sep 24, 2024
f8c9597
Merge branch 'lix-integration' into csv-app2
martin-lysk Sep 24, 2024
ec73158
copies file from source if it does not exist in target
martin-lysk Sep 24, 2024
8d647c4
flip the rows in the History view and the arrow
jannesblobel Sep 24, 2024
032a7a5
Remove unnecessary attributes
jannesblobel Sep 24, 2024
ec48767
add name
samuelstroschein Sep 24, 2024
509b9e7
chore: update package lock
samuelstroschein Sep 24, 2024
7bd3288
add process.env.port for deployment
samuelstroschein Sep 24, 2024
7b45eeb
fix: port
samuelstroschein Sep 24, 2024
88f53a2
chore: remove unused import
samuelstroschein Sep 24, 2024
42fdb51
add plugin to export
samuelstroschein Sep 24, 2024
722ebff
Merge pull request #3145 from opral/add-export
martin-lysk Sep 24, 2024
0f7c322
Merge commit '8c1b4842b0652563af48e0aa805c7dda3baa5794' into csv-app2
martin-lysk Sep 24, 2024
8be743f
changes file insert to file_internal when creating a copy from source…
martin-lysk Sep 24, 2024
8f05a07
fixes file insert
martin-lysk Sep 24, 2024
c0179d4
adds cors headers
martin-lysk Sep 24, 2024
de41938
WIP - adds a fetch for the lix before storing to opfs
martin-lysk Sep 25, 2024
a2eaae0
Merge commit 'b0d27032125779906e5a653c4536e234d0ec1fd8' into csv-app2
martin-lysk Sep 25, 2024
4491b19
Merge pull request #3144 from opral/filp-history-rows
NilsJacobsen Sep 25, 2024
950e54f
fixes build error
martin-lysk Sep 25, 2024
e98ed28
Merge branch 'csv-app2' of github.com:opral/monorepo into csv-app2
martin-lysk Sep 25, 2024
d16740c
wip: sync
NilsJacobsen Sep 25, 2024
ba1a260
WIP sync works, change server url to localhost
martin-lysk Sep 25, 2024
5ffd48e
wip: add user position
NilsJacobsen Sep 25, 2024
c8fdde1
changes the type file to fileSnapshot - syncing of the json should wo…
martin-lysk Sep 25, 2024
f08be55
wip: add user position highlighter
NilsJacobsen Sep 26, 2024
5737915
fixes memory leak
martin-lysk Sep 26, 2024
ca70c57
Merge branch 'csv-app2' of github.com:opral/monorepo into csv-app2
martin-lysk Sep 26, 2024
37a5777
point to render again
martin-lysk Sep 26, 2024
807835d
fixes lix closing and changes server urls
martin-lysk Sep 26, 2024
35ed9bb
fix: sync only current project
NilsJacobsen Sep 26, 2024
3f6b890
fixes syncing
martin-lysk Sep 26, 2024
81be097
feat: add initals next to user position
NilsJacobsen Sep 26, 2024
d9009d7
Merge branch 'lix-integration' into csv-app2
martin-lysk Sep 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions lix/packages/csv-app2-server/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
24 changes: 24 additions & 0 deletions lix/packages/csv-app2-server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
4 changes: 4 additions & 0 deletions lix/packages/csv-app2-server/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"useTabs": true,
"trailingComma": "es5"
}
8 changes: 8 additions & 0 deletions lix/packages/csv-app2-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```
npm install
npm run dev
```

```
open http://localhost:3000
```
19 changes: 19 additions & 0 deletions lix/packages/csv-app2-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "csv-app2-server",
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"test": "vitest run"
},
"dependencies": {
"@hono/node-server": "^1.13.1",
"@lix-js/sdk": "workspace:*",
"@lix-js/csv-app2": "workspace:*",
"hono": "^4.6.3"
},
"devDependencies": {
"@types/node": "^20.11.17",
"tsx": "^4.7.1",
"vitest": "^2.0.5"
}
}
135 changes: 135 additions & 0 deletions lix/packages/csv-app2-server/src/endpoint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { describe, test, expect } from "vitest";
import { app } from "./index";
import fs from "node:fs/promises";
import { newLixFile, openLixInMemory, merge } from "@lix-js/sdk";
import { plugin } from "@lix-js/csv-app2/lix-csv-plugin";

describe("hono app tes", () => {
test("get /lix-file/:id non existing", async () => {
const res = await app.request("/lix-file/i-dont-exist");
expect(res.status).toBe(400);
});

test("post /lix-file/:id", async () => {
const projectName = "new-one";
const user1newLixProjectBlob = await newLixFile();
const user1newProject = await openLixInMemory({
blob: user1newLixProjectBlob,
providePlugins: [plugin],
});

const demoCsv = await fs.readFile("./testdata/demo.csv", "utf-8");

user1newProject.currentAuthor.set("Demo User1");
await user1newProject.db
.insertInto("file")
.values([
{
id: "demo1",
path: "/data.csv",
data: await new Blob([demoCsv]).arrayBuffer(),
metadata: {
unique_column: "Stakeholder",
demo: true,
},
},
])
.execute();

const res = await app.request("/lix-file/" + projectName, {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
body: await user1newProject.toBlob(),
});

const content = await res.arrayBuffer();

const serverLix = await openLixInMemory({
blob: new Blob([content]),
providePlugins: [plugin],
});

const res2 = await app.request("/lix-file/" + projectName);
const content2 = await res2.arrayBuffer();

expect(new Blob([content])).toStrictEqual(new Blob([content2]));

const user2Lix = await openLixInMemory({
blob: new Blob([content]),
providePlugins: [plugin],
});
user2Lix.currentAuthor.set("Demo User2");

await user2Lix.db
.insertInto("file")
.values([
{
id: "demo2",
path: "/data2.csv",
data: await new Blob([demoCsv]).arrayBuffer(),
metadata: {
unique_column: "Stakeholder",
demo: true,
},
},
])
.execute();

await user2Lix.db
.insertInto("file")
.values([
{
id: "Demo User2_position",
path: "/Demo User2_position.json",
data: new TextEncoder().encode(
JSON.stringify({
position: { rowId: "test", cellName: "column-name" },
})
),
},
])
.execute();

await user2Lix.settled();
const resUser2Push = await app.request("/lix-file/" + projectName, {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
body: await user2Lix.toBlob(),
});

const resUser1Push = await app.request("/lix-file/" + projectName, {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
body: await user1newProject.toBlob(),
});

const user1PushResult = await openLixInMemory({
blob: new Blob([await resUser1Push.arrayBuffer()]),
providePlugins: [plugin],
});

// await merge({
// sourceLix: user1PushResult,
// targetLix: user1newProject,
// });

const changes = await user1newProject.db
.selectFrom("change")
.selectAll()
.where("change.file_id", "=", "demo1")
.execute();
// console.log(await
// user1PushResult
// .db.selectFrom("file")
// .selectAll()
// // .where("path", "like", "%.json")
// .execute()
// );
});
});
108 changes: 108 additions & 0 deletions lix/packages/csv-app2-server/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { serve } from "@hono/node-server";
import { openLixInMemory, merge } from "@lix-js/sdk";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { plugin } from "@lix-js/csv-app2/lix-csv-plugin";

export const app = new Hono();

// Apply CORS middleware globally
app.use('*', cors({
origin: '*',
allowMethods: ['GET', 'POST', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization'],
}));

setInterval(() => {
const before = process.memoryUsage().heapUsed / 1024 / 1024;
global.gc?.();
const after = process.memoryUsage().heapUsed / 1024 / 1024;
console.log({ before: before.toFixed(2), after: after.toFixed(2) });
}, 10_000);

const lixFiles = new Map<string, Blob>();

// A Map to track locks for each ID to ensure synchronization
const locks = new Map<string, Promise<Response>>();

// Function to handle locking per ID
async function synchronized(id: string, fn: () => Promise<Response>) {
const previous = locks.get(id) || Promise.resolve();
const current = previous.then(fn).finally(() => {
// Once done, remove the lock for the ID
if (locks.get(id) === current) {
locks.delete(id);
}
});
locks.set(id, current);
return current;
}

app.post("/lix-file/:id", async (c) => {
const { id } = c.req.param();

// Get the binary data from the request body
const buffer = await c.req.arrayBuffer();
const clientBlob = new Uint8Array(buffer);

const serverStateBlob = lixFiles.get(id);

return synchronized(id, async () => {
if (!serverStateBlob) {
const serverLix = await openLixInMemory({
blob: new Blob([clientBlob]),
providePlugins: [plugin],
});

lixFiles.set(id, await serverLix.toBlob());

await serverLix.close();
// Return the new binary data
return c.body(await lixFiles.get(id)!.arrayBuffer(), 200, {
"Content-Type": "application/octet-stream",
});
}

const clientLix = await openLixInMemory({
blob: new Blob([clientBlob]),
providePlugins: [plugin],
});

const serverLix = await openLixInMemory({
blob: serverStateBlob,
providePlugins: [plugin],
});

// console.log(clientLix.db.selectFrom())

await merge({ sourceLix: clientLix, targetLix: serverLix });
lixFiles.set(id, await serverLix.toBlob());

await serverLix.close();

await clientLix.close();
// Return the new binary data
return c.body(await lixFiles.get(id)!.arrayBuffer(), 200, {
"Content-Type": "application/octet-stream",
});
});
});

app.get("/lix-file/:id", async (c) => {
const { id } = c.req.param();

if (!lixFiles.get(id)) {
return c.text("no lix file found", 400);
}

return c.body(await lixFiles.get(id)!.arrayBuffer(), 200, {
"Content-Type": "application/octet-stream",
});
});

const port = process.env.PORT ? Number(process.env.PORT) : 3000;

serve({
fetch: app.fetch,
port,
});
21 changes: 21 additions & 0 deletions lix/packages/csv-app2-server/testdata/demo.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
seq;name;first;last
1;Pearl Griffin;Adelaide;Hopkins
2;Gregory Perry;Dorothy;Stanley
3;Noah Young;Johnny;Nichols
4;John Ray;Philip;Long
5;Eliza Lawson;Rhoda;Hawkins
6;Fanny Pearson;Cameron;Malone
7;Christina Haynes;Walter;Miller
8;Cora Rowe;Tom;Cummings
9;Carl Green;Timothy;Murray
10;Susan Patton;Alma;Wheeler
11;Justin Lowe;Ralph;Stephens
12;Franklin Watkins;Lloyd;Franklin
13;Glen West;Rachel;Joseph
14;Frances Henderson;Susan;Luna
15;Roy Simmons;Lillie;Goodman
16;Mike Barber;Louise;Chavez
17;Cecilia Hoffman;Leonard;James
18;Estelle Pierce;Gavin;Barrett
19;Clayton Zimmerman;Douglas;Wheeler
20;Arthur Wells;Ann;Burns
14 changes: 14 additions & 0 deletions lix/packages/csv-app2-server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"skipLibCheck": true,
"types": [
"node"
],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
}
}
18 changes: 18 additions & 0 deletions lix/packages/csv-app2/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
Loading
Loading