{"id":50529339,"url":"https://github.com/codemix/graph","last_synced_at":"2026-06-03T11:30:47.566Z","repository":{"id":350461061,"uuid":"1205133509","full_name":"codemix/graph","owner":"codemix","description":"A type-safe, realtime, collaborative Graph Database which runs inside a CRDT","archived":false,"fork":false,"pushed_at":"2026-04-10T14:14:21.000Z","size":1011,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T14:15:45.284Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codemix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-08T17:05:07.000Z","updated_at":"2026-04-10T14:14:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/codemix/graph","commit_stats":null,"previous_names":["codemix/graph"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/codemix/graph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemix%2Fgraph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemix%2Fgraph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemix%2Fgraph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemix%2Fgraph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codemix","download_url":"https://codeload.github.com/codemix/graph/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemix%2Fgraph/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33863265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-03T11:30:46.588Z","updated_at":"2026-06-03T11:30:47.558Z","avatar_url":"https://github.com/codemix.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://codemix.com/\"\u003e\n    \u003cimg src=\"./codemix-logo.png\" alt=\"codemix\" width=\"240\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# @codemix/graph\n\nA fully type-safe, TypeScript-first in-memory property graph database with a Cypher-like query language, a **type-safe [TinkerPop](https://tinkerpop.apache.org/) / [Gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin)-style traversal API** (`GraphTraversal`), multiple index types, and pluggable storage adapters including a [Yjs](https://yjs.dev/) CRDT-based adapter for collaborative/realtime/offline-first use.\n\nThis is the knowledge graph database for the [codemix](https://codemix.com/) product intelligence platform.\n\n## Packages\n\n| Package                                                  | Description                                                                                 |\n| -------------------------------------------------------- | ------------------------------------------------------------------------------------------- |\n| [`@codemix/graph`](./packages/graph)                     | Core graph database: Cypher queries + type-safe Gremlin-style traversals (`GraphTraversal`) |\n| [`@codemix/text-search`](./packages/text-search)         | BM25-based full-text search with English stemming                                           |\n| [`@codemix/y-graph-storage`](./packages/y-graph-storage) | [Yjs](https://yjs.dev/) CRDT storage adapter for collaborative/offline-first use            |\n\n---\n\n## `@codemix/graph`\n\nA fully typed, in-memory graph database. Vertices and edges are strongly typed against a user-defined schema. You can query with a subset of [Cypher](https://neo4j.com/docs/cypher-manual/current/) **or** with a fluent, **type-safe [Apache TinkerPop](https://tinkerpop.apache.org/) / [Gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin)-style API** — see [`GraphTraversal`](./packages/graph/README.md#type-safe-tinkerpop--gremlin-traversal-api) in the package docs.\n\n### Features\n\n- **Type-safe TinkerPop / Gremlin traversals** — `GraphTraversal` exposes familiar steps (`V()`, `E()`, `out()`, `in()`, `both()`, `hasLabel()`, `as()` / `select()`, `repeat()` …) with schema-derived typing on paths and properties; pairs with `AsyncGraph.query` for remote execution\n- **Cypher query language** — parsed via a PEG grammar, supporting `MATCH`, `WHERE`, `RETURN`, `CREATE`, `SET`, `DELETE`, `MERGE`, `UNWIND`, `UNION`, `WITH`, multi-statement queries, and more\n- **Strongly typed schema** — vertex/edge labels and their properties are defined once and inferred throughout\n- **Standard Schema validation** — property values are validated using [Standard Schema](https://standardschema.dev/) compatible validators (works with Zod, Valibot, etc.)\n- **Multiple index types** — hash (O(1) equality), B-tree (O(log n) range), and full-text (BM25-scored)\n- **Async/distributed graph** — `AsyncGraph` supports serializable operations for use across network boundaries\n- **Readonly mode** — parse queries with `readonly: true` to prevent mutation steps\n\n### Installation\n\n```bash\npnpm add @codemix/graph\n```\n\n### Development\n\nRunning `pnpm install` in the monorepo configures Git to use the tracked hooks in `.githooks`.\n\nThe pre-commit hook formats staged supported source files with `oxfmt` and restages them automatically. You can re-run the hook setup at any time with `pnpm run setup:hooks`.\n\n### Quick Start\n\n```typescript\nimport { Graph, GraphSchema } from \"@codemix/graph\";\nimport { InMemoryGraphStorage } from \"@codemix/graph\";\nimport * as z from \"zod\";\n\n// 1. Define your schema\nconst schema = {\n  vertices: {\n    Person: {\n      properties: {\n        name: { type: z.string() },\n        age: { type: z.number() },\n      },\n    },\n  },\n  edges: {\n    knows: { properties: {} },\n  },\n} as const satisfies GraphSchema;\n\n// 2. Create the graph\nconst graph = new Graph({\n  schema,\n  storage: new InMemoryGraphStorage(),\n});\n\n// 3. Add data\nconst alice = graph.addVertex(\"Person\", { name: \"Alice\", age: 30 });\nconst bob = graph.addVertex(\"Person\", { name: \"Bob\", age: 25 });\ngraph.addEdge(alice, \"knows\", bob, {});\n\n// 4. Query with Cypher\nconst results = graph.query(\"MATCH (a:Person)-[:knows]-\u003e(b:Person) RETURN a.name, b.name\");\n// [{ a: { name: \"Alice\" }, b: { name: \"Bob\" } }]\n```\n\n### Type-safe Gremlin-style traversals\n\nThe same graph is navigable with a fluent API modeled on [Apache TinkerPop Gremlin](https://tinkerpop.apache.org/docs/current/reference/#gremlin); labels and properties stay typed end-to-end:\n\n```typescript\nimport { GraphTraversal } from \"@codemix/graph\";\n\nconst g = new GraphTraversal(graph);\nfor (const path of g.V().hasLabel(\"Person\").out(\"knows\")) {\n  console.log(path.value.get(\"name\"));\n}\n```\n\nSee the [type-safe TinkerPop / Gremlin traversal API](./packages/graph/README.md#type-safe-tinkerpop--gremlin-traversal-api) section in `@codemix/graph` for the full step reference.\n\n### Defining a Schema\n\n```typescript\nimport { GraphSchema } from \"@codemix/graph\";\nimport * as z from \"zod\";\n\nconst schema = {\n  vertices: {\n    Product: {\n      properties: {\n        sku: { type: z.string() },\n        price: { type: z.number().positive() },\n        name: {\n          type: z.string(),\n          index: { type: \"fulltext\" }, // full-text search index\n        },\n      },\n      indexes: {\n        sku: { type: \"hash\", unique: true }, // unique hash index\n      },\n    },\n  },\n  edges: {\n    PURCHASED: {\n      properties: {\n        quantity: { type: z.number().int().positive() },\n      },\n    },\n  },\n} as const satisfies GraphSchema;\n```\n\n### Index Types\n\n| Type       | Lookup      | Use case                                                 |\n| ---------- | ----------- | -------------------------------------------------------- |\n| `hash`     | O(1)        | Equality (`=`) on high-cardinality properties            |\n| `btree`    | O(log n)    | Range queries (`\u003e`, `\u003c`, `\u003e=`, `\u003c=`, `BETWEEN`)          |\n| `fulltext` | BM25 scored | `CONTAINS` / free-text search via `@codemix/text-search` |\n\nAll index types support a `unique: true` constraint that throws `UniqueConstraintViolationError` on duplicate values.\n\n### Supported Cypher Features\n\n- `MATCH` with node and relationship patterns, variable-length paths (`*1..5`), shortest path\n- `WHERE` with boolean logic, property access, `IN`, `STARTS WITH`, `ENDS WITH`, `CONTAINS`, `IS NULL`, `IS NOT NULL`, label expressions (`IS LABELED`)\n- `RETURN` with aliases (`AS`), `DISTINCT`, `ORDER BY`, `SKIP`, `LIMIT`\n- `CREATE`, `SET`, `DELETE`, `REMOVE`, `MERGE`\n- `WITH` (pipeline intermediate results)\n- `UNWIND`\n- `UNION` / `UNION ALL`\n- Multi-statement queries (semicolon-separated)\n- `CALL` procedures (built-in and custom via `ProcedureRegistry`)\n- Aggregation functions: `COUNT`, `SUM`, `AVG`, `MIN`, `MAX`, `COLLECT`\n- List comprehensions, pattern comprehensions, `REDUCE`, `EXISTS` subqueries\n- Temporal types: `date`, `datetime`, `localtime`, `localdatetime`, `duration`\n- Arithmetic, string functions, math functions, type conversion functions\n- `CASE` expressions (simple and searched)\n\n### Parsing Queries\n\nFor advanced use cases, you can parse a query to a step plan without running it:\n\n```typescript\nimport { parseQueryToSteps } from \"@codemix/graph\";\n\nconst { steps, postprocess } = parseQueryToSteps(\n  \"MATCH (n:Person) RETURN n.name\",\n  { readonly: true }, // throws ReadonlyGraphError if query mutates\n);\n```\n\n### Custom Functions and Procedures\n\n```typescript\nimport { functionRegistry, procedureRegistry } from \"@codemix/graph\";\n\n// Register a custom scalar function\nfunctionRegistry.register(\"myLib.greet\", {\n  call: ([name]) =\u003e `Hello, ${name}!`,\n});\n\n// Register a custom procedure\nprocedureRegistry.register(\"myLib.listItems\", {\n  call: function* (ctx, [], yields) {\n    yield { item: \"foo\" };\n    yield { item: \"bar\" };\n  },\n});\n```\n\n### AsyncGraph\n\n`AsyncGraph` wraps a regular `Graph` and exposes mutations as serializable operation objects. This is useful for sending graph mutations over a network or message bus.\n\n```typescript\nimport { AsyncGraph } from \"@codemix/graph\";\n\nconst asyncGraph = new AsyncGraph({\n  schema,\n  storage: new InMemoryGraphStorage(),\n});\n\n// Subscribe to operations emitted by writes\nasyncGraph.on(\"operation\", (op) =\u003e {\n  sendToRemote(op); // op is a plain JSON-serializable object\n});\n\nasyncGraph.addVertex(\"Person\", { name: \"Alice\", age: 30 });\n```\n\n---\n\n## `@codemix/text-search`\n\nA lightweight, dependency-free full-text search library used internally by `@codemix/graph` for full-text indexes.\n\n### Features\n\n- BM25-inspired relevance scoring\n- English word stemming\n- Works on plain strings — no indexing infrastructure required\n\n### Usage\n\n```typescript\nimport { createMatcher, rankDocuments } from \"@codemix/text-search\";\n\n// Score a single document\nconst match = createMatcher(\"quick brown fox\");\nmatch(\"The quick brown fox jumps over the lazy dog\"); // ~0.85\nmatch(\"A slow gray elephant\"); // ~0.0\n\n// Rank a list of documents\nconst results = rankDocuments(\"database performance\", [\n  \"How to improve database query performance\",\n  \"Database connection pooling best practices\",\n  \"Unrelated article about cooking\",\n]);\n// Returns documents sorted by relevance score descending\n```\n\n---\n\n## `@codemix/y-graph-storage`\n\nA [Yjs](https://yjs.dev/) CRDT-backed storage adapter for `@codemix/graph`. Enables real-time collaborative and offline-first graph databases that sync automatically between peers.\n\n### Features\n\n- Stores graph data inside a `Y.Doc` — compatible with any Yjs provider (WebSocket, WebRTC, IndexedDB, etc.)\n- Observable — subscribe to vertex/edge changes reactively\n- Zod integration via `ZodYTypes` helpers for schema validation\n\n### Usage\n\n```typescript\nimport * as Y from \"yjs\";\nimport { Graph } from \"@codemix/graph\";\nimport { YGraphStorage } from \"@codemix/y-graph-storage\";\n\nconst doc = new Y.Doc();\nconst storage = new YGraphStorage(doc, schema);\nconst graph = new Graph({ schema, storage });\n\n// Changes to the graph are automatically reflected in the Y.Doc\n// and will sync to connected peers via any Yjs provider\ngraph.addVertex(\"Person\", { name: \"Alice\", age: 30 });\n```\n\n---\n\n## Development\n\nThis is a pnpm monorepo managed with [pnpm workspaces](https://pnpm.io/workspaces).\n\n### Prerequisites\n\n- Node.js 20+\n- pnpm 9+\n\n### Setup\n\n```bash\npnpm install\n```\n\n### Common Commands\n\n| Command              | Description                                |\n| -------------------- | ------------------------------------------ |\n| `pnpm test`          | Run all tests across packages (watch mode) |\n| `pnpm test:coverage` | Run all tests with coverage report         |\n| `pnpm build`         | Build all packages                         |\n| `pnpm typecheck`     | Type-check all packages                    |\n| `pnpm lint`          | Lint with oxlint                           |\n| `pnpm lint:fix`      | Lint and auto-fix                          |\n| `pnpm format`        | Format with oxfmt                          |\n| `pnpm format:check`  | Check formatting                           |\n\n### Package-level commands\n\n```bash\n# Run tests for a single package\npnpm --filter @codemix/graph test\n\n# Build a single package\npnpm --filter @codemix/graph build\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemix%2Fgraph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodemix%2Fgraph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemix%2Fgraph/lists"}