From fbeb4456b44be05fe2b2f88b95681a2994465f49 Mon Sep 17 00:00:00 2001 From: Gabriel Fonseca Date: Mon, 9 Nov 2026 23:27:31 +0000 Subject: [PATCH 1/5] chore: rename project to graph-kit (@graph-kit/*) Rename the monorepo from graph-om to graph-kit and republish scope as @graph-kit. - Root package: graph-om -> graph-kit (private), bin graph-kit - Packages: @graph-om/* -> @graph-kit/* (cli, sdk, zod, mcp, migrate, testing) - All imports, docs, tests, changeset linked set, turbo env vars, vitest aliases, docker names, and graph-kit.config.ts files updated - pnpm-lock.yaml regenerated (workspace links updated) Not yet published to npm (requires npm auth). --- .changeset/config.json | 12 +- .devcontainer/Dockerfile | 2 +- .devcontainer/devcontainer.json | 4 +- .github/ISSUE_TEMPLATE/BUG_REPORT.md | 6 +- .github/ISSUE_TEMPLATE/CONFIG.yml | 6 +- .github/workflows/ci.yml | 2 +- .size-limit.json | 66 +-- CONTRIBUTING.md | 8 +- PLAN.md | 148 ++--- README.md | 28 +- SECURITY.md | 2 +- bin/index.js | 6 +- docker-compose.yml | 6 +- docker/Dockerfile | 10 +- docker/docker-compose.yml | 16 +- docs/API_REFERENCE.md | 10 +- docs/ARCHITECTURE.md | 20 +- docs/CLI_REFERENCE.md | 22 +- docs/CONFIGURATION.md | 28 +- docs/CONTRIBUTING_GUIDE.md | 12 +- docs/ENVIRONMENT_VARIABLES.md | 16 +- docs/GETTING_STARTED.md | 44 +- docs/errors.md | 10 +- examples/aggregations/.env.example | 3 + .../graph.config.ts} | 2 +- examples/aggregations/package.json | 25 + examples/aggregations/src/index.ts | 75 +++ examples/aggregations/src/schema.ts | 34 ++ examples/aggregations/tsconfig.json | 12 + examples/aggregations/vitest.config.ts | 15 + examples/bulk-operations/.env.example | 3 + examples/bulk-operations/graph.config.ts | 16 + examples/bulk-operations/package.json | 25 + examples/bulk-operations/src/index.ts | 86 +++ examples/bulk-operations/src/schema.ts | 21 + examples/bulk-operations/tsconfig.json | 12 + examples/bulk-operations/vitest.config.ts | 15 + examples/configuration/.env.example | 3 + examples/configuration/graph.config.ts | 16 + examples/configuration/package.json | 25 + examples/configuration/src/index.ts | 55 ++ examples/configuration/src/schema.ts | 10 + examples/configuration/tsconfig.json | 12 + examples/configuration/vitest.config.ts | 15 + examples/crud-operations/.env.example | 3 + examples/crud-operations/graph.config.ts | 16 + examples/crud-operations/package.json | 25 + examples/crud-operations/src/index.ts | 98 ++++ examples/crud-operations/src/schema.ts | 37 ++ examples/crud-operations/tsconfig.json | 12 + examples/crud-operations/vitest.config.ts | 15 + examples/error-handling/.env.example | 3 + examples/error-handling/graph.config.ts | 16 + examples/error-handling/package.json | 25 + examples/error-handling/src/index.ts | 72 +++ examples/error-handling/src/schema.ts | 10 + examples/error-handling/tsconfig.json | 12 + examples/error-handling/vitest.config.ts | 15 + examples/graphql-schema/.env.example | 3 + examples/graphql-schema/graph.config.ts | 16 + examples/graphql-schema/package.json | 26 + examples/graphql-schema/src/index.ts | 65 +++ examples/graphql-schema/src/schema.ts | 39 ++ examples/graphql-schema/tsconfig.json | 12 + examples/graphql-schema/vitest.config.ts | 16 + examples/migrations/.env.example | 3 + examples/migrations/graph.config.ts | 16 + .../20240115143000_initial_schema.ts | 33 ++ .../migrations/20240116100000_add_user_bio.ts | 19 + examples/migrations/package.json | 25 + examples/migrations/src/index.ts | 62 +++ examples/migrations/src/schema.ts | 21 + examples/migrations/tsconfig.json | 12 + examples/migrations/vitest.config.ts | 19 + examples/mock-driver-testing/.env.example | 3 + examples/mock-driver-testing/graph.config.ts | 16 + examples/mock-driver-testing/package.json | 25 + examples/mock-driver-testing/src/index.ts | 55 ++ examples/mock-driver-testing/src/schema.ts | 21 + examples/mock-driver-testing/tsconfig.json | 12 + examples/mock-driver-testing/vitest.config.ts | 15 + examples/multi-driver/.env.example | 3 + examples/multi-driver/graph.config.ts | 16 + examples/multi-driver/package.json | 25 + examples/multi-driver/src/index.ts | 85 +++ examples/multi-driver/src/schema.ts | 21 + examples/multi-driver/tsconfig.json | 12 + examples/multi-driver/vitest.config.ts | 15 + examples/observability/.env.example | 3 + examples/observability/graph.config.ts | 16 + examples/observability/package.json | 25 + examples/observability/src/index.ts | 69 +++ examples/observability/src/schema.ts | 21 + examples/observability/tsconfig.json | 12 + examples/observability/vitest.config.ts | 15 + examples/pagination/.env.example | 3 + examples/pagination/graph.config.ts | 16 + examples/pagination/package.json | 25 + examples/pagination/src/index.ts | 70 +++ examples/pagination/src/schema.ts | 21 + examples/pagination/tsconfig.json | 12 + examples/pagination/vitest.config.ts | 15 + examples/path-traversal/.env.example | 3 + examples/path-traversal/graph.config.ts | 16 + examples/path-traversal/package.json | 25 + examples/path-traversal/src/index.ts | 70 +++ examples/path-traversal/src/schema.ts | 18 + examples/path-traversal/tsconfig.json | 12 + examples/path-traversal/vitest.config.ts | 15 + examples/query-filters/.env.example | 3 + examples/query-filters/graph.config.ts | 16 + examples/query-filters/package.json | 25 + examples/query-filters/src/index.ts | 72 +++ examples/query-filters/src/schema.ts | 21 + examples/query-filters/tsconfig.json | 12 + examples/query-filters/vitest.config.ts | 15 + examples/raw-cypher/.env.example | 3 + examples/raw-cypher/graph.config.ts | 16 + examples/raw-cypher/package.json | 25 + examples/raw-cypher/src/index.ts | 71 +++ examples/raw-cypher/src/schema.ts | 36 ++ examples/raw-cypher/tsconfig.json | 12 + examples/raw-cypher/vitest.config.ts | 15 + examples/relations/.env.example | 3 + examples/relations/graph.config.ts | 16 + examples/relations/package.json | 25 + examples/relations/src/index.ts | 85 +++ examples/relations/src/schema.ts | 40 ++ examples/relations/tsconfig.json | 12 + examples/relations/vitest.config.ts | 15 + examples/schema-definition/.env.example | 3 + examples/schema-definition/graph.config.ts | 16 + examples/schema-definition/package.json | 25 + examples/schema-definition/src/index.ts | 137 +++++ examples/schema-definition/src/schema.ts | 80 +++ examples/schema-definition/tsconfig.json | 12 + examples/schema-definition/vitest.config.ts | 15 + examples/seeding/.env.example | 3 + examples/seeding/graph.config.ts | 16 + examples/seeding/package.json | 25 + examples/seeding/src/index.ts | 75 +++ examples/seeding/src/schema.ts | 35 ++ examples/seeding/tsconfig.json | 12 + examples/seeding/vitest.config.ts | 15 + examples/selective-fields/.env.example | 3 + examples/selective-fields/graph.config.ts | 16 + examples/selective-fields/package.json | 25 + examples/selective-fields/src/index.ts | 62 +++ examples/selective-fields/src/schema.ts | 23 + examples/selective-fields/tsconfig.json | 12 + examples/selective-fields/vitest.config.ts | 15 + examples/social-graph/graph.config.ts | 16 + .../20240115143000_initial_schema.ts | 4 +- .../migrations/20240116100000_add_user_bio.ts | 4 +- .../20240117120000_add_post_viewcount_tags.ts | 4 +- .../20240118150000_add_user_profile_image.ts | 4 +- .../20240119110000_add_bookmark_relation.ts | 4 +- examples/social-graph/package.json | 8 +- examples/social-graph/src/aggregations.ts | 4 +- examples/social-graph/src/comprehensive.ts | 10 +- .../social-graph/src/errors-constraints.ts | 4 +- examples/social-graph/src/errors-handling.ts | 4 +- examples/social-graph/src/errors-public.ts | 8 +- examples/social-graph/src/errors-retry.ts | 4 +- examples/social-graph/src/graphql.ts | 8 +- examples/social-graph/src/includes.ts | 4 +- examples/social-graph/src/index.ts | 6 +- examples/social-graph/src/migrations.ts | 6 +- examples/social-graph/src/pagination.ts | 4 +- examples/social-graph/src/schema.ts | 2 +- examples/social-graph/src/seed.ts | 4 +- examples/social-graph/src/testing.ts | 4 +- examples/social-graph/src/transactions.ts | 4 +- examples/social-graph/tsconfig.json | 2 +- examples/social-graph/vitest.config.ts | 12 +- examples/transactions/.env.example | 3 + examples/transactions/graph.config.ts | 16 + examples/transactions/package.json | 25 + examples/transactions/src/index.ts | 78 +++ examples/transactions/src/schema.ts | 37 ++ examples/transactions/tsconfig.json | 12 + examples/transactions/vitest.config.ts | 15 + examples/zod-validation/.env.example | 3 + examples/zod-validation/graph.config.ts | 16 + examples/zod-validation/package.json | 27 + examples/zod-validation/src/index.ts | 78 +++ examples/zod-validation/src/schema.ts | 21 + examples/zod-validation/tsconfig.json | 16 + examples/zod-validation/vitest.config.ts | 16 + package.json | 12 +- packages/cli/README.md | 14 +- packages/cli/package.json | 16 +- packages/cli/src/commands/diff.ts | 12 +- packages/cli/src/commands/generate.ts | 40 +- packages/cli/src/commands/init.ts | 28 +- packages/cli/src/commands/migrate.ts | 24 +- packages/cli/src/commands/seed.ts | 18 +- packages/cli/src/commands/studio.ts | 6 +- packages/cli/src/index.ts | 12 +- packages/cli/src/version.ts | 4 +- packages/cli/tests/generate.test.ts | 22 +- packages/cli/tests/init.test.ts | 16 +- packages/cli/tsup.config.ts | 4 +- packages/cli/vitest.config.ts | 16 +- packages/mcp/README.md | 22 +- packages/mcp/package.json | 14 +- packages/mcp/src/config.ts | 4 +- packages/mcp/src/index.ts | 6 +- packages/mcp/src/resources/index.ts | 2 +- .../mcp/src/resources/resource-handler.ts | 4 +- packages/mcp/src/server/index.ts | 4 +- packages/mcp/src/server/mcp-server.ts | 18 +- packages/mcp/src/tools/index.ts | 2 +- packages/mcp/src/tools/tool-error.ts | 4 +- packages/mcp/src/tools/tool-handler.ts | 6 +- packages/mcp/tests/server.test.ts | 12 +- packages/mcp/tsup.config.ts | 4 +- packages/migrate/README.md | 18 +- packages/migrate/package.json | 14 +- packages/migrate/src/index.ts | 4 +- packages/migrate/src/model/index.ts | 2 +- packages/migrate/src/model/migration.ts | 4 +- packages/migrate/src/runner/index.ts | 2 +- .../migrate/src/runner/migration-options.ts | 4 +- .../migrate/src/runner/migration-runner.ts | 12 +- packages/migrate/src/schema/index.ts | 2 +- packages/migrate/src/schema/schema-diff.ts | 4 +- packages/migrate/src/template/index.ts | 2 +- .../src/template/migration-template.ts | 8 +- packages/migrate/src/version/index.ts | 2 +- packages/migrate/src/version/version.ts | 2 +- packages/migrate/tests/runner.test.ts | 2 +- packages/migrate/tsup.config.ts | 4 +- packages/sdk/README.md | 84 +-- packages/sdk/THIRD_PARTY_NOTICES.md | 2 +- packages/sdk/package.json | 10 +- packages/sdk/src/auth/index.ts | 4 +- packages/sdk/src/batch/index.ts | 4 +- packages/sdk/src/benchmark/index.ts | 6 +- packages/sdk/src/client/index.ts | 4 +- packages/sdk/src/config/index.ts | 19 +- packages/sdk/src/config/keys.ts | 4 +- packages/sdk/src/driver/falkordb.ts | 2 +- packages/sdk/src/driver/index.ts | 2 +- packages/sdk/src/driver/kuzu.ts | 2 +- packages/sdk/src/driver/memgraph.ts | 2 +- packages/sdk/src/driver/neo4j.ts | 2 +- packages/sdk/src/errors/index.ts | 26 +- packages/sdk/src/graphql/index.ts | 4 +- packages/sdk/src/index.ts | 4 +- packages/sdk/src/migration/index.ts | 10 +- packages/sdk/src/observability/index.ts | 4 +- packages/sdk/src/otel/index.ts | 6 +- packages/sdk/src/query/index.ts | 2 +- packages/sdk/src/schema/index.ts | 2 +- packages/sdk/src/schema/parser.ts | 2 +- packages/sdk/src/seed/index.ts | 4 +- packages/sdk/src/testing/index.ts | 6 +- packages/sdk/src/types/index.ts | 4 +- packages/sdk/src/visualization/index.ts | 4 +- packages/sdk/tests/config.test.ts | 6 +- packages/sdk/tests/driver-falkordb.test.ts | 2 +- packages/sdk/tests/driver-kuzu.test.ts | 2 +- packages/sdk/tests/driver-memgraph.test.ts | 2 +- packages/sdk/tests/driver-neo4j.test.ts | 6 +- packages/sdk/tests/driver-registry.test.ts | 2 +- packages/sdk/tests/error-surfaces.test.ts | 4 +- packages/sdk/tests/errors.test.ts | 10 +- .../sdk/tests/integration-falkordb.test.ts | 2 +- packages/sdk/tests/integration-kuzu.test.ts | 4 +- .../sdk/tests/integration-memgraph.test.ts | 2 +- packages/sdk/tests/integration.test.ts | 2 +- packages/sdk/tests/schema-builder.test.ts | 2 +- packages/sdk/tsconfig.json | 2 +- packages/sdk/tsup.config.ts | 2 +- packages/testing/README.md | 14 +- packages/testing/package.json | 14 +- packages/testing/src/driver/index.ts | 2 +- packages/testing/src/driver/mock-driver.ts | 4 +- packages/testing/src/fixtures/index.ts | 2 +- .../testing/src/fixtures/test-fixtures.ts | 2 +- packages/testing/src/generators/index.ts | 2 +- packages/testing/src/generators/random.ts | 2 +- packages/testing/src/index.ts | 8 +- .../testing/src/matchers/graph-matchers.ts | 4 +- packages/testing/src/matchers/index.ts | 2 +- packages/testing/tsup.config.ts | 4 +- packages/zod/README.md | 14 +- packages/zod/package.json | 16 +- packages/zod/src/index.ts | 4 +- packages/zod/src/schema/factory.ts | 4 +- packages/zod/src/schema/index.ts | 2 +- packages/zod/src/schema/property.ts | 4 +- packages/zod/src/schema/types.ts | 4 +- packages/zod/src/validation/hooks.ts | 4 +- packages/zod/src/validation/index.ts | 2 +- packages/zod/src/validation/validate.ts | 4 +- packages/zod/tsup.config.ts | 4 +- pnpm-lock.yaml | 525 +++++++++++++++++- tests/bin.test.ts | 2 +- tests/cli_template.test.ts | 16 +- tests/env.test.ts | 26 +- tests/schema_integration.test.ts | 8 +- turbo.json | 2 +- vitest.config.ts | 2 +- 305 files changed, 4840 insertions(+), 746 deletions(-) create mode 100644 examples/aggregations/.env.example rename examples/{social-graph/graph-om.config.ts => aggregations/graph.config.ts} (88%) create mode 100644 examples/aggregations/package.json create mode 100644 examples/aggregations/src/index.ts create mode 100644 examples/aggregations/src/schema.ts create mode 100644 examples/aggregations/tsconfig.json create mode 100644 examples/aggregations/vitest.config.ts create mode 100644 examples/bulk-operations/.env.example create mode 100644 examples/bulk-operations/graph.config.ts create mode 100644 examples/bulk-operations/package.json create mode 100644 examples/bulk-operations/src/index.ts create mode 100644 examples/bulk-operations/src/schema.ts create mode 100644 examples/bulk-operations/tsconfig.json create mode 100644 examples/bulk-operations/vitest.config.ts create mode 100644 examples/configuration/.env.example create mode 100644 examples/configuration/graph.config.ts create mode 100644 examples/configuration/package.json create mode 100644 examples/configuration/src/index.ts create mode 100644 examples/configuration/src/schema.ts create mode 100644 examples/configuration/tsconfig.json create mode 100644 examples/configuration/vitest.config.ts create mode 100644 examples/crud-operations/.env.example create mode 100644 examples/crud-operations/graph.config.ts create mode 100644 examples/crud-operations/package.json create mode 100644 examples/crud-operations/src/index.ts create mode 100644 examples/crud-operations/src/schema.ts create mode 100644 examples/crud-operations/tsconfig.json create mode 100644 examples/crud-operations/vitest.config.ts create mode 100644 examples/error-handling/.env.example create mode 100644 examples/error-handling/graph.config.ts create mode 100644 examples/error-handling/package.json create mode 100644 examples/error-handling/src/index.ts create mode 100644 examples/error-handling/src/schema.ts create mode 100644 examples/error-handling/tsconfig.json create mode 100644 examples/error-handling/vitest.config.ts create mode 100644 examples/graphql-schema/.env.example create mode 100644 examples/graphql-schema/graph.config.ts create mode 100644 examples/graphql-schema/package.json create mode 100644 examples/graphql-schema/src/index.ts create mode 100644 examples/graphql-schema/src/schema.ts create mode 100644 examples/graphql-schema/tsconfig.json create mode 100644 examples/graphql-schema/vitest.config.ts create mode 100644 examples/migrations/.env.example create mode 100644 examples/migrations/graph.config.ts create mode 100644 examples/migrations/migrations/20240115143000_initial_schema.ts create mode 100644 examples/migrations/migrations/20240116100000_add_user_bio.ts create mode 100644 examples/migrations/package.json create mode 100644 examples/migrations/src/index.ts create mode 100644 examples/migrations/src/schema.ts create mode 100644 examples/migrations/tsconfig.json create mode 100644 examples/migrations/vitest.config.ts create mode 100644 examples/mock-driver-testing/.env.example create mode 100644 examples/mock-driver-testing/graph.config.ts create mode 100644 examples/mock-driver-testing/package.json create mode 100644 examples/mock-driver-testing/src/index.ts create mode 100644 examples/mock-driver-testing/src/schema.ts create mode 100644 examples/mock-driver-testing/tsconfig.json create mode 100644 examples/mock-driver-testing/vitest.config.ts create mode 100644 examples/multi-driver/.env.example create mode 100644 examples/multi-driver/graph.config.ts create mode 100644 examples/multi-driver/package.json create mode 100644 examples/multi-driver/src/index.ts create mode 100644 examples/multi-driver/src/schema.ts create mode 100644 examples/multi-driver/tsconfig.json create mode 100644 examples/multi-driver/vitest.config.ts create mode 100644 examples/observability/.env.example create mode 100644 examples/observability/graph.config.ts create mode 100644 examples/observability/package.json create mode 100644 examples/observability/src/index.ts create mode 100644 examples/observability/src/schema.ts create mode 100644 examples/observability/tsconfig.json create mode 100644 examples/observability/vitest.config.ts create mode 100644 examples/pagination/.env.example create mode 100644 examples/pagination/graph.config.ts create mode 100644 examples/pagination/package.json create mode 100644 examples/pagination/src/index.ts create mode 100644 examples/pagination/src/schema.ts create mode 100644 examples/pagination/tsconfig.json create mode 100644 examples/pagination/vitest.config.ts create mode 100644 examples/path-traversal/.env.example create mode 100644 examples/path-traversal/graph.config.ts create mode 100644 examples/path-traversal/package.json create mode 100644 examples/path-traversal/src/index.ts create mode 100644 examples/path-traversal/src/schema.ts create mode 100644 examples/path-traversal/tsconfig.json create mode 100644 examples/path-traversal/vitest.config.ts create mode 100644 examples/query-filters/.env.example create mode 100644 examples/query-filters/graph.config.ts create mode 100644 examples/query-filters/package.json create mode 100644 examples/query-filters/src/index.ts create mode 100644 examples/query-filters/src/schema.ts create mode 100644 examples/query-filters/tsconfig.json create mode 100644 examples/query-filters/vitest.config.ts create mode 100644 examples/raw-cypher/.env.example create mode 100644 examples/raw-cypher/graph.config.ts create mode 100644 examples/raw-cypher/package.json create mode 100644 examples/raw-cypher/src/index.ts create mode 100644 examples/raw-cypher/src/schema.ts create mode 100644 examples/raw-cypher/tsconfig.json create mode 100644 examples/raw-cypher/vitest.config.ts create mode 100644 examples/relations/.env.example create mode 100644 examples/relations/graph.config.ts create mode 100644 examples/relations/package.json create mode 100644 examples/relations/src/index.ts create mode 100644 examples/relations/src/schema.ts create mode 100644 examples/relations/tsconfig.json create mode 100644 examples/relations/vitest.config.ts create mode 100644 examples/schema-definition/.env.example create mode 100644 examples/schema-definition/graph.config.ts create mode 100644 examples/schema-definition/package.json create mode 100644 examples/schema-definition/src/index.ts create mode 100644 examples/schema-definition/src/schema.ts create mode 100644 examples/schema-definition/tsconfig.json create mode 100644 examples/schema-definition/vitest.config.ts create mode 100644 examples/seeding/.env.example create mode 100644 examples/seeding/graph.config.ts create mode 100644 examples/seeding/package.json create mode 100644 examples/seeding/src/index.ts create mode 100644 examples/seeding/src/schema.ts create mode 100644 examples/seeding/tsconfig.json create mode 100644 examples/seeding/vitest.config.ts create mode 100644 examples/selective-fields/.env.example create mode 100644 examples/selective-fields/graph.config.ts create mode 100644 examples/selective-fields/package.json create mode 100644 examples/selective-fields/src/index.ts create mode 100644 examples/selective-fields/src/schema.ts create mode 100644 examples/selective-fields/tsconfig.json create mode 100644 examples/selective-fields/vitest.config.ts create mode 100644 examples/social-graph/graph.config.ts create mode 100644 examples/transactions/.env.example create mode 100644 examples/transactions/graph.config.ts create mode 100644 examples/transactions/package.json create mode 100644 examples/transactions/src/index.ts create mode 100644 examples/transactions/src/schema.ts create mode 100644 examples/transactions/tsconfig.json create mode 100644 examples/transactions/vitest.config.ts create mode 100644 examples/zod-validation/.env.example create mode 100644 examples/zod-validation/graph.config.ts create mode 100644 examples/zod-validation/package.json create mode 100644 examples/zod-validation/src/index.ts create mode 100644 examples/zod-validation/src/schema.ts create mode 100644 examples/zod-validation/tsconfig.json create mode 100644 examples/zod-validation/vitest.config.ts diff --git a/.changeset/config.json b/.changeset/config.json index 04e953f..c552313 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -5,12 +5,12 @@ "fixed": [], "linked": [ [ - "@graph-om/sdk", - "@graph-om/cli", - "@graph-om/zod", - "@graph-om/mcp", - "@graph-om/migrate", - "@graph-om/testing" + "@graph-kit/sdk", + "@graph-kit/cli", + "@graph-kit/zod", + "@graph-kit/mcp", + "@graph-kit/migrate", + "@graph-kit/testing" ] ], "access": "public", diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 83622b0..2371d2b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -19,6 +19,6 @@ RUN npm install -g corepack@latest pnpm@9 USER node -WORKDIR /workspaces/graph-om +WORKDIR /workspaces/graph-kit CMD ["sleep", "infinity"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 46cd2d9..c60b3cc 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ { - "name": "Graph-OM Development", + "name": "Graph-Kit Development", "build": { "dockerfile": "Dockerfile", "context": ".." @@ -47,5 +47,5 @@ "forwardPorts": [7687, 7474, 3000], "postCreateCommand": "pnpm install && pnpm build", "remoteUser": "node", - "workspaceFolder": "/workspaces/graph-om" + "workspaceFolder": "/workspaces/graph-kit" } diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md index ee7ee82..cbfcad2 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md @@ -1,5 +1,5 @@ --- -about: Report a bug to help us improve Graph-OM +about: Report a bug to help us improve Graph-Kit title: '[BUG] ' labels: ['bug', 'triage'] assignees: ['gabrielvfonseca'] @@ -13,7 +13,7 @@ A clear and concise description of what the bug is. Steps to reproduce the behavior: -1. Run `graph-om init my-graph` +1. Run `graph-kit init my-graph` 2. Run `pnpm install` 3. Run `npx tsx src/index.ts` 4. See error @@ -27,7 +27,7 @@ A clear and concise description of what you expected to happen. - OS: [e.g. macOS, Ubuntu] - Node version: [e.g. 20.10.0] - pnpm version: [e.g. 9.15.9] -- Graph-OM version: [e.g. 1.0.0] +- Graph-Kit version: [e.g. 1.0.0] - Neo4j version: [e.g. 5.14.0] ## Additional context diff --git a/.github/ISSUE_TEMPLATE/CONFIG.yml b/.github/ISSUE_TEMPLATE/CONFIG.yml index 409da61..bf61f64 100644 --- a/.github/ISSUE_TEMPLATE/CONFIG.yml +++ b/.github/ISSUE_TEMPLATE/CONFIG.yml @@ -7,9 +7,9 @@ labels: ['triage'] blank_issues_enabled: false contact_links: - - name: Graph-OM Discord + - name: Graph-Kit Discord url: https://discord.gg/metal about: Join the community for real-time help - - name: Graph-OM Documentation - url: https://github.com/frontal-labs/graph-om/tree/master/docs + - name: Graph-Kit Documentation + url: https://github.com/frontal-labs/graph-kit/tree/master/docs about: Read the full documentation diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12780c0..89b7b8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,7 +190,7 @@ jobs: NEO4J_URI: bolt://localhost:7687 NEO4J_USER: neo4j NEO4J_PASSWORD: password - run: pnpm --filter @graph-om/sdk run benchmark:ci + run: pnpm --filter @graph-kit/sdk run benchmark:ci # Security audit security: diff --git a/.size-limit.json b/.size-limit.json index f31797e..adef96b 100644 --- a/.size-limit.json +++ b/.size-limit.json @@ -1,230 +1,230 @@ [ { - "name": "@graph-om/mcp (import)", + "name": "@graph-kit/mcp (import)", "path": "packages/mcp/dist/index.mjs", "gzip": true, "brotli": false, "limit": "1650 B" }, { - "name": "@graph-om/mcp (require)", + "name": "@graph-kit/mcp (require)", "path": "packages/mcp/dist/index.js", "gzip": true, "brotli": false, "limit": "1700 B" }, { - "name": "@graph-om/migrate (import)", + "name": "@graph-kit/migrate (import)", "path": "packages/migrate/dist/index.mjs", "gzip": true, "brotli": false, "limit": "2700 B" }, { - "name": "@graph-om/migrate (require)", + "name": "@graph-kit/migrate (require)", "path": "packages/migrate/dist/index.js", "gzip": true, "brotli": false, "limit": "2750 B" }, { - "name": "@graph-om/sdk (import)", + "name": "@graph-kit/sdk (import)", "path": "packages/sdk/dist/index.mjs", "gzip": true, "brotli": false, "limit": "246900 B" }, { - "name": "@graph-om/sdk/schema (import)", + "name": "@graph-kit/sdk/schema (import)", "path": "packages/sdk/dist/schema/index.mjs", "gzip": true, "brotli": false, "limit": "3200 B" }, { - "name": "@graph-om/sdk/client (import)", + "name": "@graph-kit/sdk/client (import)", "path": "packages/sdk/dist/client/index.mjs", "gzip": true, "brotli": false, "limit": "10750 B" }, { - "name": "@graph-om/sdk/errors (import)", + "name": "@graph-kit/sdk/errors (import)", "path": "packages/sdk/dist/errors/index.mjs", "gzip": true, "brotli": false, "limit": "7050 B" }, { - "name": "@graph-om/sdk/query (import)", + "name": "@graph-kit/sdk/query (import)", "path": "packages/sdk/dist/query/index.mjs", "gzip": true, "brotli": false, "limit": "8150 B" }, { - "name": "@graph-om/sdk/config (import)", + "name": "@graph-kit/sdk/config (import)", "path": "packages/sdk/dist/config/index.mjs", "gzip": true, "brotli": false, "limit": "1050 B" }, { - "name": "@graph-om/sdk/driver (import)", + "name": "@graph-kit/sdk/driver (import)", "path": "packages/sdk/dist/driver/index.mjs", "gzip": true, "brotli": false, "limit": "11350 B" }, { - "name": "@graph-om/sdk/driver/neo4j (import)", + "name": "@graph-kit/sdk/driver/neo4j (import)", "path": "packages/sdk/dist/driver/neo4j.mjs", "gzip": true, "brotli": false, "limit": "6350 B" }, { - "name": "@graph-om/sdk/driver/memgraph (import)", + "name": "@graph-kit/sdk/driver/memgraph (import)", "path": "packages/sdk/dist/driver/memgraph.mjs", "gzip": true, "brotli": false, "limit": "6650 B" }, { - "name": "@graph-om/sdk/driver/kuzu (import)", + "name": "@graph-kit/sdk/driver/kuzu (import)", "path": "packages/sdk/dist/driver/kuzu.mjs", "gzip": true, "brotli": false, "limit": "5900 B" }, { - "name": "@graph-om/sdk/driver/falkordb (import)", + "name": "@graph-kit/sdk/driver/falkordb (import)", "path": "packages/sdk/dist/driver/falkordb.mjs", "gzip": true, "brotli": false, "limit": "8000 B" }, { - "name": "@graph-om/sdk/migration (import)", + "name": "@graph-kit/sdk/migration (import)", "path": "packages/sdk/dist/migration/index.mjs", "gzip": true, "brotli": false, "limit": "11300 B" }, { - "name": "@graph-om/sdk/schema/parser (import)", + "name": "@graph-kit/sdk/schema/parser (import)", "path": "packages/sdk/dist/schema/parser.mjs", "gzip": true, "brotli": false, "limit": "2600 B" }, { - "name": "@graph-om/sdk/seed (import)", + "name": "@graph-kit/sdk/seed (import)", "path": "packages/sdk/dist/seed/index.mjs", "gzip": true, "brotli": false, "limit": "6550 B" }, { - "name": "@graph-om/sdk/observability (import)", + "name": "@graph-kit/sdk/observability (import)", "path": "packages/sdk/dist/observability/index.mjs", "gzip": true, "brotli": false, "limit": "7100 B" }, { - "name": "@graph-om/sdk/graphql (import)", + "name": "@graph-kit/sdk/graphql (import)", "path": "packages/sdk/dist/graphql/index.mjs", "gzip": true, "brotli": false, "limit": "8650 B" }, { - "name": "@graph-om/sdk/visualization (import)", + "name": "@graph-kit/sdk/visualization (import)", "path": "packages/sdk/dist/visualization/index.mjs", "gzip": true, "brotli": false, "limit": "7050 B" }, { - "name": "@graph-om/sdk/batch (import)", + "name": "@graph-kit/sdk/batch (import)", "path": "packages/sdk/dist/batch/index.mjs", "gzip": true, "brotli": false, "limit": "2900 B" }, { - "name": "@graph-om/sdk/auth (import)", + "name": "@graph-kit/sdk/auth (import)", "path": "packages/sdk/dist/auth/index.mjs", "gzip": true, "brotli": false, "limit": "13700 B" }, { - "name": "@graph-om/sdk/testing (import)", + "name": "@graph-kit/sdk/testing (import)", "path": "packages/sdk/dist/testing/index.mjs", "gzip": true, "brotli": false, "limit": "3550 B" }, { - "name": "@graph-om/sdk/otel (import)", + "name": "@graph-kit/sdk/otel (import)", "path": "packages/sdk/dist/otel/index.mjs", "gzip": true, "brotli": false, "limit": "207850 B" }, { - "name": "@graph-om/sdk/benchmark (import)", + "name": "@graph-kit/sdk/benchmark (import)", "path": "packages/sdk/dist/benchmark/index.mjs", "gzip": true, "brotli": false, "limit": "11400 B" }, { - "name": "@graph-om/sdk (require)", + "name": "@graph-kit/sdk (require)", "path": "packages/sdk/dist/index.js", "gzip": true, "brotli": false, "limit": "247650 B" }, { - "name": "@graph-om/testing (import)", + "name": "@graph-kit/testing (import)", "path": "packages/testing/dist/index.mjs", "gzip": true, "brotli": false, "limit": "2250 B" }, { - "name": "@graph-om/testing (require)", + "name": "@graph-kit/testing (require)", "path": "packages/testing/dist/index.js", "gzip": true, "brotli": false, "limit": "2300 B" }, { - "name": "@graph-om/zod (import)", + "name": "@graph-kit/zod (import)", "path": "packages/zod/dist/index.mjs", "gzip": true, "brotli": false, "limit": "900 B" }, { - "name": "@graph-om/zod (require)", + "name": "@graph-kit/zod (require)", "path": "packages/zod/dist/index.js", "gzip": true, "brotli": false, "limit": "950 B" }, { - "name": "@graph-om/cli bin (import)", + "name": "@graph-kit/cli bin (import)", "path": "packages/cli/dist/index.mjs", "gzip": true, "brotli": false, "limit": "13300 B" }, { - "name": "@graph-om/cli (require)", + "name": "@graph-kit/cli (require)", "path": "packages/cli/dist/index.js", "gzip": true, "brotli": false, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d17b50e..7a1df51 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ -# Contributing to Graph-OM +# Contributing to Graph-Kit Thanks for your interest in contributing! ## Getting started ```bash -git clone https://github.com/frontal-labs/graph-om.git -cd graph-om +git clone https://github.com/frontal-labs/graph-kit.git +cd graph-kit pnpm install pnpm build pnpm test @@ -36,7 +36,7 @@ Requirements: **Node.js ≥ 20** and **pnpm 9** (`corepack enable` recommended). ## Project layout - `packages/sdk` — schema DSL, Cypher compiler, client, config, and the driver adapters (`src/driver/`: Neo4j, Memgraph, Kuzu, FalkorDB) -- `cli` — `graph-om init` / `graph-om generate` +- `cli` — `graph-kit init` / `graph-kit generate` - `packages/zod` — Zod validation integration - `examples/social-graph` — end-to-end example app diff --git a/PLAN.md b/PLAN.md index 29ffe4e..0f66ecb 100644 --- a/PLAN.md +++ b/PLAN.md @@ -1,7 +1,7 @@ -# GraphOM --- Agent Refactor & Implementation Master Plan +# GraphKit --- Agent Refactor & Implementation Master Plan **Status:** Proposed execution brief\ -**Project:** Rename and evolve `metal` into **GraphOM** (`graph-om` for +**Project:** Rename and evolve `metal` into **GraphKit** (`graph-kit` for repository/CLI naming where appropriate)\ **Primary implementation target:** Existing Metal TypeScript/Neo4j repository\ @@ -15,11 +15,11 @@ exists. ## 0. Mission for the coding agents -Transform the existing Metal project into **GraphOM**, a +Transform the existing Metal project into **GraphKit**, a TypeScript-first graph development and verification platform, initially focused on Neo4j. -GraphOM must help developers and coding agents: +GraphKit must help developers and coding agents: 1. Understand an existing graph and its application contracts. 2. Model graph structure and business invariants. @@ -33,7 +33,7 @@ GraphOM must help developers and coding agents: **Product positioning** -> GraphOM --- The graph engineering and verification platform for +> GraphKit --- The graph engineering and verification platform for > developers and AI coding agents. Suggested tagline: **Build with confidence. Evolve without fear.** @@ -61,7 +61,7 @@ agent-facing verification. unknown database. - Diagnostics are read-only by default. Migrations and repairs require explicit plans and approval. -- AI agents may propose changes; GraphOM must validate them; a human +- AI agents may propose changes; GraphKit must validate them; a human or explicitly authorized pipeline approves risky execution. - Distinguish static analysis from database-backed measurements. Never present estimates as actual Neo4j execution statistics. @@ -90,7 +90,7 @@ declaration challenges in TypeScript ORM ecosystems. - Transaction timeout, rollback and failure-handling complexity. **Evidence limitation:** These are observations from adjacent graph and -ORM ecosystems, not validated customer research for Metal/GraphOM. The +ORM ecosystems, not validated customer research for Metal/GraphKit. The supplied research stated that Metal itself had no open GitHub issues and very limited visible adoption signals at the time of inspection. Treat the pain points as hypotheses to validate, not proven demand. @@ -136,7 +136,7 @@ strategy discussion include: operations. Do not build a thin MCP wrapper that merely repeats database access. - **Neo4j Agent Skills:** coding-agent guidance for Neo4j, Cypher, - modeling, indexing and profiling. GraphOM must provide + modeling, indexing and profiling. GraphKit must provide project-specific contracts, change analysis and verification beyond generic instructions. - **Neo4j native tooling:** schema inspection, constraints, indexes, @@ -148,7 +148,7 @@ releases, repositories and issue trackers before claiming that a capability is missing from a competitor. Distinguish verified facts from interpretation. -**Strategic hypothesis:** GraphOM's potential advantage is making +**Strategic hypothesis:** GraphKit's potential advantage is making AI-generated graph application changes verifiable, safe and consistent with both the declared contract and the live database. @@ -156,9 +156,9 @@ with both the declared contract and the live database. ## 3. Target architecture -### 3.1 Canonical GraphOM Schema IR +### 3.1 Canonical GraphKit Schema IR -Create or identify one canonical, versioned **GraphOM Schema +Create or identify one canonical, versioned **GraphKit Schema Intermediate Representation (IR)**. It should be the shared source consumed by: @@ -211,19 +211,19 @@ telemetry. The previous strategy proposed these eventual logical packages: -- `@graphom/core` -- `@graphom/compiler` -- `@graphom/neo4j` -- `@graphom/validation` -- `@graphom/cli` -- `@graphom/migrate` -- `@graphom/doctor` -- `@graphom/testing` -- `@graphom/query-inspector` -- `@graphom/studio` -- `@graphom/observe` -- `@graphom/ai` -- `@graphom/mcp` +- `@graphkit/core` +- `@graphkit/compiler` +- `@graphkit/neo4j` +- `@graphkit/validation` +- `@graphkit/cli` +- `@graphkit/migrate` +- `@graphkit/doctor` +- `@graphkit/testing` +- `@graphkit/query-inspector` +- `@graphkit/studio` +- `@graphkit/observe` +- `@graphkit/ai` +- `@graphkit/mcp` These are **candidate boundaries, not a mandate to create thirteen packages now**. First map the existing four-package architecture and @@ -237,13 +237,13 @@ reason to change them. ### 3.4 Naming and compatibility -- Product name: **GraphOM**. -- Repository/CLI convention: `graph-om` / `graphom`, chosen +- Product name: **GraphKit**. +- Repository/CLI convention: `graph-kit` / `graphkit`, chosen consistently after checking current repository and npm naming constraints. -- Proposed package scope: `@graphom/*`, subject to availability and +- Proposed package scope: `@graphkit/*`, subject to availability and ownership verification. -- Plan a compatibility path from `metal` to GraphOM: package rename, +- Plan a compatibility path from `metal` to GraphKit: package rename, import migration, CLI migration, documentation links, release notes and deprecation policy. - Do not break existing consumers silently. If the project is @@ -284,9 +284,9 @@ compile-time, runtime, database-enforced or test-only. Command concept: ``` bash -npx graph-om doctor -npx graph-om doctor --json -npx graph-om doctor --explain +npx graph-kit doctor +npx graph-kit doctor --json +npx graph-kit doctor --explain ``` Potential checks, subject to technical feasibility and explicit scope: - @@ -313,15 +313,15 @@ cases. - Avoid false certainty: a check that cannot be completed reports Illustrative output (not a claim about current implementation): ``` text -GraphOM Doctor +GraphKit Doctor ERROR Missing uniqueness constraint: User.email WARNING Schema drift: undeclared relationship type REVIEWED WARNING Data invariant: 42 User nodes missing required property email Suggested next steps: - graph-om doctor --explain - graph-om migrate plan - graph-om validate + graph-kit doctor --explain + graph-kit migrate plan + graph-kit validate ``` ### 4.3 Safe Graph Migrations --- production adoption capability @@ -329,10 +329,10 @@ Suggested next steps: Command concepts: ``` bash -graph-om migrate diff -graph-om migrate plan -graph-om migrate apply -graph-om migrate status +graph-kit migrate diff +graph-kit migrate plan +graph-kit migrate apply +graph-kit migrate status ``` Required capabilities, staged: - Schema snapshots. - Contract diffs. - @@ -371,7 +371,7 @@ applying changes. Two separate modes must be exposed: -1. **Static analysis:** inspect GraphOM query AST/generated Cypher and +1. **Static analysis:** inspect GraphKit query AST/generated Cypher and known contract metadata without running the query. 2. **Database-backed inspection:** use Neo4j `EXPLAIN` / `PROFILE` and report actual plan/runtime data when available. @@ -424,7 +424,7 @@ all parents. Potential API concepts: ``` ts -import { graphTest } from "@graphom/testing"; +import { graphTest } from "@graphkit/testing"; await graphTest(client) .createNode("User", { id: "u1" }) @@ -477,7 +477,7 @@ A coding agent should be able to understand the project's graph contract, propose a change, implement it, run deterministic checks and present a safe migration plan. -GraphOM is not a replacement for Claude Code, Codex, Cursor, VS Code +GraphKit is not a replacement for Claude Code, Codex, Cursor, VS Code agents or Neo4j MCP. It is the graph-specific engineering and verification layer they can use. @@ -496,11 +496,11 @@ verification layer they can use. ### 5.3 MCP tool design -Candidate read/analysis tools: - `graphom.get_project_context` - -`graphom.get_schema` - `graphom.inspect_database` - -`graphom.validate_contract` - `graphom.analyze_change` - -`graphom.plan_migration` - `graphom.explain_query` - -`graphom.run_graph_tests` - `graphom.check_drift` +Candidate read/analysis tools: - `graphkit.get_project_context` - +`graphkit.get_schema` - `graphkit.inspect_database` - +`graphkit.validate_contract` - `graphkit.analyze_change` - +`graphkit.plan_migration` - `graphkit.explain_query` - +`graphkit.run_graph_tests` - `graphkit.check_drift` Separate read-only analysis from mutation tools. If mutation tools are added later: - Require explicit environment and operation scope. - @@ -510,7 +510,7 @@ production authorization. ### 5.4 Skills and agent instructions -Ship: - A GraphOM Agent Skill with workflows for modeling, queries, +Ship: - A GraphKit Agent Skill with workflows for modeling, queries, migrations, diagnostics and testing. - `AGENTS.md` guidance and examples. - Provider-specific setup documentation only where tested. - CLI commands with stable machine-readable JSON output and meaningful @@ -540,19 +540,19 @@ database. - The agent reports checks and unresolved risks honestly. Candidate commands (adapt to existing conventions): ``` bash -graph-om init -graph-om introspect -graph-om generate -graph-om validate -graph-om doctor -graph-om migrate diff -graph-om migrate plan -graph-om migrate apply -graph-om migrate status -graph-om inspect -graph-om query explain -graph-om studio -graph-om test +graph-kit init +graph-kit introspect +graph-kit generate +graph-kit validate +graph-kit doctor +graph-kit migrate diff +graph-kit migrate plan +graph-kit migrate apply +graph-kit migrate status +graph-kit inspect +graph-kit query explain +graph-kit studio +graph-kit test ``` Requirements: - `--help` and actionable errors. - Human and JSON @@ -631,7 +631,7 @@ repository audit and team-capacity review. **Exit gate:** The team can explain what exists, what is missing, what can be reused and how to test changes safely. -### Phase 1 --- Core correctness and GraphOM identity (approximately weeks 3--7) +### Phase 1 --- Core correctness and GraphKit identity (approximately weeks 3--7) - Fix compiler/AST correctness issues. - Verify generated Cypher and parameterization. @@ -639,7 +639,7 @@ can be reused and how to test changes safely. - Establish or formalize canonical schema IR. - Establish type-generation correctness. - Add deterministic compiler tests and public API tests. -- Introduce GraphOM naming in docs/internal metadata with a +- Introduce GraphKit naming in docs/internal metadata with a compatibility plan. **Exit gate:** Reliable core, repeatable builds, meaningful tests, @@ -720,7 +720,7 @@ security, documentation and adoption evidence. - [ ] Transaction/session lifecycle audit. - [ ] Disposable Neo4j integration test environment. - [ ] Canonical IR decision. -- [ ] GraphOM naming and compatibility decision. +- [ ] GraphKit naming and compatibility decision. ### P1 --- First differentiated release @@ -746,7 +746,7 @@ security, documentation and adoption evidence. ### P3 --- Agent/ecosystem expansion - [ ] MCP read/analysis server. -- [ ] Portable GraphOM Agent Skill. +- [ ] Portable GraphKit Agent Skill. - [ ] `AGENTS.md` templates. - [ ] Agent end-to-end tests. - [ ] Studio. @@ -796,7 +796,7 @@ security, documentation and adoption evidence. - Query inspection modes. - Agent/MCP setup. - Security and production deployment. -- Metal-to-GraphOM upgrade path. +- Metal-to-GraphKit upgrade path. ------------------------------------------------------------------------ @@ -820,9 +820,9 @@ Measure: - Time to complete representative tasks. - Issues detected before deployment. - False-positive and false-negative rates. - Migration plan accuracy and recovery outcomes. - Agent task completion rate. - Human interventions required. - Developer trust and willingness -to keep using GraphOM. +to keep using GraphKit. -A key product test: **Would developers miss GraphOM if they returned to +A key product test: **Would developers miss GraphKit if they returned to their previous workflow?** ------------------------------------------------------------------------ @@ -856,7 +856,7 @@ items as `UNKNOWN` and investigate them. Use this as the initial task for the primary coding agent: > You are the lead engineer responsible for evolving the existing Metal -> TypeScript/Neo4j project into GraphOM. +> TypeScript/Neo4j project into GraphKit. > > Read `GRAPHOM_AGENT_IMPLEMENTATION_PLAN.md` completely before changing > code. @@ -891,7 +891,7 @@ Use this as the initial task for the primary coding agent: > Keep static query analysis separate from actual Neo4j > `EXPLAIN`/`PROFILE` measurements. Do not overstate estimates. Treat > MCP/agent output and graph data as untrusted. Do not let an AI agent -> bypass GraphOM's validation or authorization. +> bypass GraphKit's validation or authorization. > > Do not attempt all roadmap phases in one task. Work in small vertical > slices with tests, documentation and reviewable commits. Stop and ask @@ -929,9 +929,9 @@ edits to shared compiler, package manifests or generated files. ------------------------------------------------------------------------ -## 15. Definition of GraphOM 1.0 +## 15. Definition of GraphKit 1.0 -Do not call GraphOM 1.0 ready until: +Do not call GraphKit 1.0 ready until: - The core TypeScript API and compiler are stable and documented. - Neo4j support and supported versions are explicit. @@ -944,9 +944,9 @@ Do not call GraphOM 1.0 ready until: - Graph-aware tests can run safely in CI. - Agent/MCP workflows are documented and permission-scoped. - Security, compatibility and release procedures are tested. -- A developer can adopt GraphOM on an existing Neo4j project without +- A developer can adopt GraphKit on an existing Neo4j project without an unsafe rewrite. -**Final product principle:** GraphOM should make graph applications +**Final product principle:** GraphKit should make graph applications easier to understand, safer to change, easier to debug and more predictable to operate --- for both humans and AI coding agents. diff --git a/README.md b/README.md index 84315aa..9fd83a5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GraphOM +# GraphKit ![Frontal Banner](./banner.jpg) @@ -15,7 +15,7 @@ A schema-first TypeScript library for modelling, querying, and traversing graph │ └──────────────────┘ ▼ │ ┌────────────────┐ ┌───────────────┐ ▼ -│ @graph-om/sdk │────▶│ DriverAdapter │◀─── GraphClient(driver, nodes) +│ @graph-kit/sdk │────▶│ DriverAdapter │◀─── GraphClient(driver, nodes) │ QueryCompiler │ └───────────────┘ └────────────────┘ ▲ ``` @@ -24,15 +24,15 @@ A schema-first TypeScript library for modelling, querying, and traversing graph | Package | Description | | --- | --- | -| [`@graph-om/sdk`](./packages/sdk) | Schema DSL, Cypher query compiler, typed client, config system | -| [`@graph-om/cli`](./packages/cli) | `graph init` and `graph generate` codegen | -| [`@graph-om/zod`](./packages/zod) | Zod schema generation and validation from node configs | +| [`@graph-kit/sdk`](./packages/sdk) | Schema DSL, Cypher query compiler, typed client, config system | +| [`@graph-kit/cli`](./packages/cli) | `graph init` and `graph generate` codegen | +| [`@graph-kit/zod`](./packages/zod) | Zod schema generation and validation from node configs | ## Quick start ```bash # scaffold a project -npx @graph-om/cli init my-graph +npx @graph-kit/cli init my-graph cd my-graph pnpm install # or npm / yarn cp .env.example .env # set NEO4J_URI / NEO4J_USER / NEO4J_PASSWORD @@ -44,7 +44,7 @@ npx tsx src/index.ts ```ts // src/schema.ts -import { node, relation, schema as sch, string, boolean, date } from '@graph-om/sdk'; +import { node, relation, schema as sch, string, boolean, date } from '@graph-kit/sdk'; export const User = node('User') .add('id', string({ primary: true })) @@ -66,8 +66,8 @@ export const graph = sch().add('User', User).add('Post', Post).build(); ### Query the graph ```ts -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ @@ -109,7 +109,7 @@ await client.transaction(async (tx) => { ### Validate with Zod ```ts -import { toCreateSchema, validateCreate } from '@graph-om/zod'; +import { toCreateSchema, validateCreate } from '@graph-kit/zod'; import { User } from './schema.js'; const result = validateCreate(User, { id: '1', name: 'Alice' }); @@ -118,10 +118,10 @@ if (!result.success) console.error(result.error.flatten()); ## Handling errors -Every failure graph-om throws is a typed `GraphError` with a stable `code`, so you can branch on it rather than on the message: +Every failure graph-kit throws is a typed `GraphError` with a stable `code`, so you can branch on it rather than on the message: ```ts -import { hasCode } from '@graph-om/sdk/errors'; +import { hasCode } from '@graph-kit/sdk/errors'; try { await client.update('Person', { where: { id }, data }); @@ -133,14 +133,14 @@ try { } ``` -Driver errors keep the original error on `cause`. Before sending an error to a client, convert it with `toPublic`, so the client sees only the code and a fixed message. See [docs/errors.md](https://github.com/frontal-labs/graph-om/blob/main/docs/errors.md) for every code. +Driver errors keep the original error on `cause`. Before sending an error to a client, convert it with `toPublic`, so the client sees only the code and a fixed message. See [docs/errors.md](https://github.com/frontal-labs/graph-kit/blob/main/docs/errors.md) for every code. ## Configuration `graph.config.ts` drives codegen: ```ts -import { defineConfig } from '@graph-om/sdk'; +import { defineConfig } from '@graph-kit/sdk'; export default defineConfig({ schema: './src/schema.ts', diff --git a/SECURITY.md b/SECURITY.md index 4e31071..89a953c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,7 +2,7 @@ ## Supported versions -Only the latest published version of each `@graph-om/*` package receives security fixes. +Only the latest published version of each `@graph-kit/*` package receives security fixes. ## Reporting a vulnerability diff --git a/bin/index.js b/bin/index.js index 881aa5c..c61f013 100755 --- a/bin/index.js +++ b/bin/index.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -// Root launcher for the graph-om CLI. It runs the built CLI from packages/cli, so the +// Root launcher for the graph-kit CLI. It runs the built CLI from packages/cli, so the // command works from the repository root on macOS, Linux and Windows. const fs = require('node:fs'); const path = require('node:path'); @@ -7,14 +7,14 @@ const { pathToFileURL } = require('node:url'); const [major] = process.versions.node.split('.').map(Number); if (major < 22) { - console.error(`graph-om needs Node.js 22 or newer; this is ${process.versions.node}.`); + console.error(`graph-kit needs Node.js 22 or newer; this is ${process.versions.node}.`); process.exit(1); } const cliEntry = path.resolve(__dirname, '..', 'packages', 'cli', 'dist', 'index.mjs'); if (!fs.existsSync(cliEntry)) { - console.error(`graph-om: the CLI is not built yet (missing ${cliEntry}).`); + console.error(`graph-kit: the CLI is not built yet (missing ${cliEntry}).`); console.error('Run "pnpm build" from the repository root, then try again.'); process.exit(1); } diff --git a/docker-compose.yml b/docker-compose.yml index 975818b..bf113e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: neo4j: image: neo4j:5 - container_name: graph-om-neo4j + container_name: graph-kit-neo4j ports: - "7474:7474" - "7687:7687" @@ -10,7 +10,7 @@ services: NEO4J_server_memory_heap_initial__size: 512m NEO4J_server_memory_heap_max__size: 1G volumes: - - graph-om-neo4j-data:/data + - graph-kit-neo4j-data:/data healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:7474 || exit 1"] interval: 10s @@ -18,4 +18,4 @@ services: retries: 10 volumes: - graph-om-neo4j-data: + graph-kit-neo4j-data: diff --git a/docker/Dockerfile b/docker/Dockerfile index 850a0d5..d360d07 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,9 +2,9 @@ ARG NODE_VERSION=20 FROM node:${NODE_VERSION}-slim AS base -LABEL org.opencontainers.image.description="Graph-OM - Prisma-like DX for graph databases" -LABEL org.opencontainers.image.url="https://github.com/frontal-labs/graph-om" -LABEL org.opencontainers.image.source="https://github.com/frontal-labs/graph-om.git" +LABEL org.opencontainers.image.description="Graph-Kit - Prisma-like DX for graph databases" +LABEL org.opencontainers.image.url="https://github.com/frontal-labs/graph-kit" +LABEL org.opencontainers.image.source="https://github.com/frontal-labs/graph-kit.git" WORKDIR /app @@ -48,7 +48,7 @@ WORKDIR /app ENV NODE_ENV=production RUN addgroup --system --gid 1001 nodejs \ - && adduser --system --uid 1001 graph-om + && adduser --system --uid 1001 graph-kit COPY --from=builder /app/packages ./packages COPY --from=builder /app/packages/cli ./packages/cli @@ -57,7 +57,7 @@ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json COPY --from=builder /app/pnpm-workspace.yaml ./pnpm-workspace.yaml -USER graph-om +USER graph-kit EXPOSE 3000 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 98a4de0..d889fbd 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,7 +1,7 @@ services: neo4j: image: neo4j:5.17-community - container_name: graph-om-neo4j + container_name: graph-kit-neo4j environment: NEO4J_AUTH: neo4j/password NEO4J_PLUGINS: '["apoc"]' @@ -24,12 +24,12 @@ services: retries: 10 start_period: 30s - graph-om: + graph-kit: build: context: .. dockerfile: docker/Dockerfile target: runner - container_name: graph-om-app + container_name: graph-kit-app depends_on: neo4j: condition: service_healthy @@ -39,7 +39,7 @@ services: NEO4J_USER: neo4j NEO4J_PASSWORD: password NEO4J_DATABASE: neo4j - GRAPH_OM_DEBUG: "false" + GRAPH_KIT_DEBUG: "false" ports: - "3000:3000" volumes: @@ -48,12 +48,12 @@ services: - ./packages/cli:/app/packages/cli restart: unless-stopped - graph-om-dev: + graph-kit-dev: build: context: .. dockerfile: docker/Dockerfile target: builder - container_name: graph-om-dev + container_name: graph-kit-dev depends_on: neo4j: condition: service_healthy @@ -63,7 +63,7 @@ services: NEO4J_USER: neo4j NEO4J_PASSWORD: password NEO4J_DATABASE: neo4j - GRAPH_OM_DEBUG: "true" + GRAPH_KIT_DEBUG: "true" ports: - "3000:3000" - "9229:9229" @@ -81,4 +81,4 @@ volumes: networks: default: - name: graph-om-network + name: graph-kit-network diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index e2755df..a4507fe 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -1,6 +1,6 @@ # API Reference -## @graph-om/sdk +## @graph-kit/sdk ### Schema DSL @@ -125,14 +125,14 @@ Get default config shape. Validated environment variables (see ENVIRONMENT_VARIABLES.md). -## @graph-om/sdk/driver/neo4j +## @graph-kit/sdk/driver/neo4j ### `createNeo4jDriver(config)` Create a Neo4j driver adapter. ```ts -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; const driver = createNeo4jDriver({ uri: env.NEO4J_URI, @@ -146,6 +146,6 @@ await driver.connect(); await driver.disconnect(); ``` -## @graph-om/zod +## @graph-kit/zod -Zod validation integration for Graph-OM schemas. Generates zod schemas alongside TypeScript types when `output.zod: true` in `graph-om.config.ts`. +Zod validation integration for Graph-Kit schemas. Generates zod schemas alongside TypeScript types when `output.zod: true` in `graph-kit.config.ts`. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 40cba8e..09dc910 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,6 +1,6 @@ # Architecture -Graph-OM follows a layered architecture inspired by Prisma and Drizzle. +Graph-Kit follows a layered architecture inspired by Prisma and Drizzle. ## Layers @@ -15,7 +15,7 @@ schema() → .add() → .rel() → .build() → GraphSchemaRegistry ### 2. Cypher Compiler (`packages/sdk/src/query`) -Compiles Graph-OM operations (find, create, update, delete, include) into Cypher queries and parameters. Type-safe via generics over `NodeConfig`. +Compiles Graph-Kit operations (find, create, update, delete, include) into Cypher queries and parameters. Type-safe via generics over `NodeConfig`. ### 3. Client (`packages/sdk/src/client`) @@ -33,18 +33,18 @@ All adapters abstract connection management and query execution behind a common ### 5. CLI (`packages/cli/`) -`@graph-om/cli` provides `graph-om init` (scaffolding) and `graph-om generate` (code generation from schema). +`@graph-kit/cli` provides `graph-kit init` (scaffolding) and `graph-kit generate` (code generation from schema). ### 6. Zod Integration (`packages/zod`) -Generates zod validation schemas from Graph-OM node configs when `output.zod: true`. +Generates zod validation schemas from Graph-Kit node configs when `output.zod: true`. ## Data Flow ``` User Schema (schema.ts) ↓ -graph-om generate +graph-kit generate ↓ Generated Types + Client (src/__generated__/) ↓ @@ -68,11 +68,11 @@ Driver Adapter (query execution) ## Project Structure ``` -graph-om/ -├── packages/cli/ # @graph-om/cli — scaffolding + codegen -├── packages/sdk/ # @graph-om/sdk — schema, compiler, client, config -│ ├── sdk/driver/ # @graph-om/sdk/driver/* — Neo4j, Memgraph, Kuzu, FalkorDB adapters (inside packages/sdk) -├── packages/zod/ # @graph-om/zod — zod validation +graph-kit/ +├── packages/cli/ # @graph-kit/cli — scaffolding + codegen +├── packages/sdk/ # @graph-kit/sdk — schema, compiler, client, config +│ ├── sdk/driver/ # @graph-kit/sdk/driver/* — Neo4j, Memgraph, Kuzu, FalkorDB adapters (inside packages/sdk) +├── packages/zod/ # @graph-kit/zod — zod validation ├── examples/social-graph/ # End-to-end demo └── docs/ # Documentation ``` diff --git a/docs/CLI_REFERENCE.md b/docs/CLI_REFERENCE.md index 62e9571..144a622 100644 --- a/docs/CLI_REFERENCE.md +++ b/docs/CLI_REFERENCE.md @@ -1,10 +1,10 @@ # CLI Reference -The Graph-OM CLI (`@graph-om/cli`) provides `graph-om init` and `graph-om generate` commands. +The Graph-Kit CLI (`@graph-kit/cli`) provides `graph-kit init` and `graph-kit generate` commands. ## Installation -The CLI is installed as part of the Graph-OM monorepo: +The CLI is installed as part of the Graph-Kit monorepo: ```bash pnpm install @@ -13,15 +13,15 @@ pnpm install Or for a standalone project: ```bash -pnpm add @graph-om/cli +pnpm add @graph-kit/cli ``` -## `graph-om init ` +## `graph-kit init ` -Scaffolds a new Graph-OM project. +Scaffolds a new Graph-Kit project. ``` -graph-om init [--database ] +graph-kit init [--database ] ``` | Argument | Description | Default | @@ -34,11 +34,11 @@ graph-om init [--database ] **Generated files:** -- `package.json` — Project manifest with Graph-OM dependencies +- `package.json` — Project manifest with Graph-Kit dependencies - `tsconfig.json` — TypeScript configuration - `src/schema.ts` — Graph schema definition - `src/index.ts` — Application entrypoint -- `graph-om.config.ts` — Graph-OM configuration +- `graph-kit.config.ts` — Graph-Kit configuration - `.env.example` — Environment variable template **Next steps after init:** @@ -51,12 +51,12 @@ cp .env.example .env npx tsx src/index.ts ``` -## `graph-om generate` +## `graph-kit generate` Generates types and client code from your schema. ``` -graph-om generate [--watch] +graph-kit generate [--watch] ``` | Option | Description | @@ -98,7 +98,7 @@ export async function createClient(config?: ClientConfig): Promise ## Programmatic API ```ts -import { createProgram } from '@graph-om/cli'; +import { createProgram } from '@graph-kit/cli'; const program = createProgram(); program.parse(); diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 57398e9..5a44ef9 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -1,13 +1,13 @@ # Configuration -Graph-OM configuration is centered around `defineConfig` and environment variables loaded via `env`. +Graph-Kit configuration is centered around `defineConfig` and environment variables loaded via `env`. ## defineConfig -`defineConfig` is an identity function that provides type-safety for your Graph-OM project configuration. It does not perform validation at runtime — validation happens through the `env` object. +`defineConfig` is an identity function that provides type-safety for your Graph-Kit project configuration. It does not perform validation at runtime — validation happens through the `env` object. ```ts -import { defineConfig, env } from '@graph-om/sdk'; +import { defineConfig, env } from '@graph-kit/sdk'; export default defineConfig({ schema: './src/schema.ts', @@ -24,7 +24,7 @@ export default defineConfig({ maxConnectionLifetime: undefined, maxTransactionRetryTime: undefined, }, - debug: env.GRAPH_OM_DEBUG, + debug: env.GRAPH_KIT_DEBUG, exclude: [], }); ``` @@ -63,14 +63,14 @@ export default defineConfig({ All environment variables are parsed and validated by `@t3-oss/env-core` + zod. See `packages/sdk/src/config/keys.ts` for the full schema. ```ts -import { env } from '@graph-om/sdk'; +import { env } from '@graph-kit/sdk'; // All values are typed and have defaults where applicable env.NEO4J_URI; // string env.NEO4J_USER; // string env.NEO4J_PASSWORD; // string env.NEO4J_DATABASE; // string | undefined -env.GRAPH_OM_DEBUG; // boolean +env.GRAPH_KIT_DEBUG; // boolean ``` Create a `.env` file in your project root: @@ -80,17 +80,17 @@ NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j NEO4J_PASSWORD=password NEO4J_DATABASE=neo4j -GRAPH_OM_DEBUG=false +GRAPH_KIT_DEBUG=false ``` -Copy `.env.example` to `.env` after running `graph-om init`. +Copy `.env.example` to `.env` after running `graph-kit init`. ## resolveConfig `resolveConfig` takes a `GraphConfig` and returns a fully-resolved config with defaults applied: ```ts -import { resolveConfig } from '@graph-om/sdk'; +import { resolveConfig } from '@graph-kit/sdk'; const config = resolveConfig({ schema: './src/schema.ts', @@ -110,13 +110,13 @@ const config = resolveConfig({ `loadConfig` attempts to load a config file from the project root. Supported formats: -- `graph-om.config.ts` -- `graph-om.config.mjs` -- `graph-om.config.js` -- `graph-om.config.json` +- `graph-kit.config.ts` +- `graph-kit.config.mjs` +- `graph-kit.config.js` +- `graph-kit.config.json` ```ts -import { loadConfig } from '@graph-om/sdk'; +import { loadConfig } from '@graph-kit/sdk'; const config = await loadConfig(); // or loadConfig('/path/to/project') ``` diff --git a/docs/CONTRIBUTING_GUIDE.md b/docs/CONTRIBUTING_GUIDE.md index de0b8dd..5bbe37e 100644 --- a/docs/CONTRIBUTING_GUIDE.md +++ b/docs/CONTRIBUTING_GUIDE.md @@ -3,8 +3,8 @@ ## Getting Started ```bash -git clone https://github.com/frontal-labs/graph-om.git -cd graph-om +git clone https://github.com/frontal-labs/graph-kit.git +cd graph-kit pnpm install pnpm build pnpm test @@ -43,10 +43,10 @@ Requirements: Node.js ≥ 20, pnpm 9 (`corepack enable` recommended). ## Project Layout -- `packages/cli/` — `@graph-om/cli` — `graph-om init` / `graph-om generate` -- `packages/sdk/` — `@graph-om/sdk` — schema DSL, Cypher compiler, client, config -- `packages/sdk/src/driver/` — `@graph-om/sdk/driver/*` — DriverAdapter implementations (Neo4j, Memgraph, Kuzu, FalkorDB) -- `packages/zod/` — `@graph-om/zod` — Zod validation integration +- `packages/cli/` — `@graph-kit/cli` — `graph-kit init` / `graph-kit generate` +- `packages/sdk/` — `@graph-kit/sdk` — schema DSL, Cypher compiler, client, config +- `packages/sdk/src/driver/` — `@graph-kit/sdk/driver/*` — DriverAdapter implementations (Neo4j, Memgraph, Kuzu, FalkorDB) +- `packages/zod/` — `@graph-kit/zod` — Zod validation integration - `examples/social-graph/` — end-to-end example app - `docs/` — documentation (uppercase snake_case file names) diff --git a/docs/ENVIRONMENT_VARIABLES.md b/docs/ENVIRONMENT_VARIABLES.md index eb735bf..6e3593b 100644 --- a/docs/ENVIRONMENT_VARIABLES.md +++ b/docs/ENVIRONMENT_VARIABLES.md @@ -1,6 +1,6 @@ # Environment Variables -Graph-OM uses [@t3-oss/env-core](https://env.t3.gg/) with [zod](https://zod.dev/) to validate and type environment variables. All env access goes through the `env` export from `@graph-om/sdk`. +Graph-Kit uses [@t3-oss/env-core](https://env.t3.gg/) with [zod](https://zod.dev/) to validate and type environment variables. All env access goes through the `env` export from `@graph-kit/sdk`. ## Schema Definition @@ -16,7 +16,7 @@ export const env = createEnv({ NEO4J_USER: z.string().default('neo4j'), NEO4J_PASSWORD: z.string().default('password'), NEO4J_DATABASE: z.string().optional(), - GRAPH_OM_DEBUG: z.string().optional().transform((val) => val === 'true'), + GRAPH_KIT_DEBUG: z.string().optional().transform((val) => val === 'true'), }, runtimeEnv: process.env, emptyStringAsUndefined: true, @@ -31,18 +31,18 @@ export const env = createEnv({ | `NEO4J_USER` | string | `neo4j` | Neo4j username | | `NEO4J_PASSWORD` | string | `password` | Neo4j password | | `NEO4J_DATABASE` | string \| undefined | `undefined` | Neo4j database name | -| `GRAPH_OM_DEBUG` | boolean | `false` | Enable debug mode when `true` | +| `GRAPH_KIT_DEBUG` | boolean | `false` | Enable debug mode when `true` | ## Usage ```ts -import { env } from '@graph-om/sdk'; +import { env } from '@graph-kit/sdk'; // Typed access — no process.env checks needed const uri = env.NEO4J_URI; -const debug = env.GRAPH_OM_DEBUG; +const debug = env.GRAPH_KIT_DEBUG; -// In graph-om.config.ts +// In graph-kit.config.ts export default defineConfig({ driver: { uri: env.NEO4J_URI, @@ -50,7 +50,7 @@ export default defineConfig({ password: env.NEO4J_PASSWORD, database: env.NEO4J_DATABASE, }, - debug: env.GRAPH_OM_DEBUG, + debug: env.GRAPH_KIT_DEBUG, }); ``` @@ -61,7 +61,7 @@ NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j NEO4J_PASSWORD=password NEO4J_DATABASE=neo4j -GRAPH_OM_DEBUG=false +GRAPH_KIT_DEBUG=false ``` ## Validation Behavior diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index c754e27..e6a6ba2 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -1,16 +1,16 @@ -# Graph-OM — Prisma-like DX for Graph Databases +# Graph-Kit — Prisma-like DX for Graph Databases -Graph-OM is a TypeScript OGM (Object-Graph Mapper) for graph databases, starting with Neo4j. It provides a schema DSL, Cypher query compiler, type-safe client, and CLI tooling for init and code generation. +Graph-Kit is a TypeScript OGM (Object-Graph Mapper) for graph databases, starting with Neo4j. It provides a schema DSL, Cypher query compiler, type-safe client, and CLI tooling for init and code generation. ## Project Layout ``` -graph-om/ -│ ├── cli/ # @graph-om/cli — graph-om init / graph-om generate +graph-kit/ +│ ├── cli/ # @graph-kit/cli — graph-kit init / graph-kit generate ├── packages/ -│ ├── sdk/ # @graph-om/sdk — schema DSL, Cypher compiler, client, config, drivers +│ ├── sdk/ # @graph-kit/sdk — schema DSL, Cypher compiler, client, config, drivers │ │ └── src/driver/ # Neo4j, Memgraph, Kuzu and FalkorDB adapters -│ └── zod/ # @graph-om/zod — Zod validation integration +│ └── zod/ # @graph-kit/zod — Zod validation integration ├── examples/ │ └── social-graph/ # End-to-end example app ├── docs/ # This documentation @@ -31,8 +31,8 @@ graph-om/ ### Installation ```bash -git clone https://github.com/frontal-labs/graph-om.git -cd graph-om +git clone https://github.com/frontal-labs/graph-kit.git +cd graph-kit pnpm install pnpm build ``` @@ -40,7 +40,7 @@ pnpm build ### Initialize a New Project ```bash -npx @graph-om/cli init my-graph +npx @graph-kit/cli init my-graph cd my-graph pnpm install cp .env.example .env @@ -53,16 +53,16 @@ npx tsx src/index.ts ### Environment Variables -All environment variables are validated through `@t3-oss/env-core` + zod in `packages/sdk/src/config/keys.ts`. Export `env` from `@graph-om/sdk`: +All environment variables are validated through `@t3-oss/env-core` + zod in `packages/sdk/src/config/keys.ts`. Export `env` from `@graph-kit/sdk`: ```ts -import { env } from '@graph-om/sdk'; +import { env } from '@graph-kit/sdk'; console.log(env.NEO4J_URI); // bolt://localhost:7687 (default) console.log(env.NEO4J_USER); // neo4j (default) console.log(env.NEO4J_PASSWORD); // password (default) console.log(env.NEO4J_DATABASE); // optional -console.log(env.GRAPH_OM_DEBUG); // boolean, from GRAPH_OM_DEBUG=true +console.log(env.GRAPH_KIT_DEBUG); // boolean, from GRAPH_KIT_DEBUG=true ``` | Variable | Type | Default | Required | @@ -71,12 +71,12 @@ console.log(env.GRAPH_OM_DEBUG); // boolean, from GRAPH_OM_DEBUG=true | `NEO4J_USER` | string | `neo4j` | No | | `NEO4J_PASSWORD` | string | `password` | No | | `NEO4J_DATABASE` | string \| undefined | `undefined` | No | -| `GRAPH_OM_DEBUG` | boolean | `false` | No | +| `GRAPH_KIT_DEBUG` | boolean | `false` | No | -### graph-om.config.ts +### graph-kit.config.ts ```ts -import { defineConfig, env } from '@graph-om/sdk'; +import { defineConfig, env } from '@graph-kit/sdk'; export default defineConfig({ schema: './src/schema.ts', @@ -91,7 +91,7 @@ export default defineConfig({ password: env.NEO4J_PASSWORD, database: env.NEO4J_DATABASE, }, - debug: env.GRAPH_OM_DEBUG, + debug: env.GRAPH_KIT_DEBUG, exclude: [], }); ``` @@ -101,7 +101,7 @@ export default defineConfig({ Define your graph schema with the `node`, `defineRel`, and `schema` helpers: ```ts -import { node, defineRel, schema, string, number, date } from '@graph-om/sdk'; +import { node, defineRel, schema, string, number, date } from '@graph-kit/sdk'; const User = node('User') .add('id', string({ primary: true })) @@ -130,8 +130,8 @@ const graph = schema() ## Client ```ts -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ @@ -149,11 +149,11 @@ await client.disconnect(); ## CLI -### `graph-om init ` +### `graph-kit init ` -Scaffolds a new Graph-OM project with schema, config, env example, and entrypoint. +Scaffolds a new Graph-Kit project with schema, config, env example, and entrypoint. -### `graph-om generate` +### `graph-kit generate` Generates types and client code from your schema. Supports `--watch` for auto-regeneration. diff --git a/docs/errors.md b/docs/errors.md index 9401c48..e676803 100644 --- a/docs/errors.md +++ b/docs/errors.md @@ -1,13 +1,13 @@ # Errors -Every failure graph-om throws is a `GraphError`. It extends `Error`, so `instanceof Error` and `.message` keep working, and it adds three things you can rely on: +Every failure graph-kit throws is a `GraphError`. It extends `Error`, so `instanceof Error` and `.message` keep working, and it adds three things you can rely on: - **`code`**: a stable identifier, such as `record_not_found`. Branch on it, not on the message. - **`statusCode`**: an HTTP-style status (400–599) for surfaces that map errors to responses. - **`retry`**: `{ retryable: boolean }`. Only retry when `retryable` is `true`, and only if the operation is safe to repeat. ```ts -import { hasCode } from '@graph-om/sdk/errors'; +import { hasCode } from '@graph-kit/sdk/errors'; try { await client.update('Person', { where: { id }, data }); @@ -92,7 +92,7 @@ Anchors below match the `link` that each error carries. ## query_failed - **Status:** 500 · **Retryable:** no -- **Meaning:** the database failed a query for a reason graph-om does not classify further. +- **Meaning:** the database failed a query for a reason graph-kit does not classify further. - **Typical cause:** a driver error with no specific code, or an unexpected response. - **Fix:** read `cause` and `metadata.driverCode` for the native error. @@ -106,7 +106,7 @@ Anchors below match the `link` that each error carries. ## invalid_argument - **Status:** 400 · **Retryable:** no -- **Meaning:** an argument has a value graph-om cannot use. +- **Meaning:** an argument has a value graph-kit cannot use. - **Typical cause:** an identifier that is not a valid label or property name, a non-date value for a `DateTime`, or an empty array passed where one item is needed. - **Fix:** correct the argument. @@ -156,4 +156,4 @@ Anchors below match the `link` that each error carries. ## Surfaces that face clients -Errors from the SDK carry developer detail (`message`, `cause`, `metadata`). Before sending an error to a client, convert it with `toPublic` from `@graph-om/sdk/errors`. The MCP server and the generated GraphQL resolvers already do this. The client receives only `scope`, `code` and a fixed public message, and never Cypher text, labels, values or URIs. +Errors from the SDK carry developer detail (`message`, `cause`, `metadata`). Before sending an error to a client, convert it with `toPublic` from `@graph-kit/sdk/errors`. The MCP server and the generated GraphQL resolvers already do this. The client receives only `scope`, `code` and a fixed public message, and never Cypher text, labels, values or URIs. diff --git a/examples/aggregations/.env.example b/examples/aggregations/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/aggregations/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/social-graph/graph-om.config.ts b/examples/aggregations/graph.config.ts similarity index 88% rename from examples/social-graph/graph-om.config.ts rename to examples/aggregations/graph.config.ts index 9104553..480babb 100644 --- a/examples/social-graph/graph-om.config.ts +++ b/examples/aggregations/graph.config.ts @@ -1,4 +1,4 @@ -import { defineConfig } from '@graph-om/sdk'; +import { defineConfig } from '@graph-kit/sdk'; export default defineConfig({ schema: './src/schema.ts', diff --git a/examples/aggregations/package.json b/examples/aggregations/package.json new file mode 100644 index 0000000..34d026c --- /dev/null +++ b/examples/aggregations/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-aggregations", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "count(), aggregate(), raw Cypher groups (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/aggregations/src/index.ts b/examples/aggregations/src/index.ts new file mode 100644 index 0000000..d504b1e --- /dev/null +++ b/examples/aggregations/src/index.ts @@ -0,0 +1,75 @@ +// index.ts - count(), aggregate(), raw Cypher groups +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type PostRow, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'agg-' DETACH DELETE n"); + + const users = [ + { id: 'agg-alice', name: 'Alice', age: 28 }, + { id: 'agg-bob', name: 'Bob', age: 32 }, + { id: 'agg-carol', name: 'Carol', age: 25 }, + { id: 'agg-dave', name: 'Dave', age: 30 }, + ]; + for (const u of users) { + await client.create('User', { data: u }); + } + await client.create('Post', { + data: { id: 'agg-post-1', title: 'Published', published: true, viewCount: 10 }, + }); + await client.create('Post', { + data: { id: 'agg-post-2', title: 'Draft', published: false, viewCount: 3 }, + }); + await client.create('Post', { + data: { id: 'agg-post-3', title: 'Popular', published: true, viewCount: 50 }, + }); + + console.log('--- count ---'); + console.log('total users:', await client.count('User')); + console.log('users age>=30:', await client.count('User', { age: { gte: 30 } })); + console.log('published posts:', await client.count('Post', { published: true })); + + console.log('\n--- aggregate ---'); + console.log('avg age:', await client.aggregate('User', 'avg', 'age')); + console.log('min age:', await client.aggregate('User', 'min', 'age')); + console.log('max age:', await client.aggregate('User', 'max', 'age')); + console.log('sum viewCount:', await client.aggregate('Post', 'sum', 'viewCount')); + + console.log('\n--- raw Cypher groups ---'); + const byPublished = await client.raw<{ published: boolean; postCount: number }>( + 'MATCH (p:Post) RETURN p.published AS published, count(p) AS postCount ORDER BY published', + ); + for (const row of byPublished) { + console.log(`published=${row.published}: ${row.postCount} post(s)`); + } + + const avgByAge = await client.raw<{ age: number; avgAge: number }>( + 'MATCH (u:User) RETURN u.age AS age, avg(u.age) AS avgAge ORDER BY age', + ); + for (const row of avgByAge) { + console.log(`age ${row.age}: avg ${row.avgAge}`); + } + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/aggregations/src/schema.ts b/examples/aggregations/src/schema.ts new file mode 100644 index 0000000..98d8868 --- /dev/null +++ b/examples/aggregations/src/schema.ts @@ -0,0 +1,34 @@ +// schema.ts - Aggregations example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('published', { type: 'boolean', default: false }) + .add('viewCount', number({ default: 0 })) + .add('createdAt', date({ default: () => new Date() })) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + age: number | null; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + published: boolean; + viewCount: number; + createdAt: Date; +}; diff --git a/examples/aggregations/tsconfig.json b/examples/aggregations/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/aggregations/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/aggregations/vitest.config.ts b/examples/aggregations/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/aggregations/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/bulk-operations/.env.example b/examples/bulk-operations/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/bulk-operations/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/bulk-operations/graph.config.ts b/examples/bulk-operations/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/bulk-operations/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/bulk-operations/package.json b/examples/bulk-operations/package.json new file mode 100644 index 0000000..1f5453b --- /dev/null +++ b/examples/bulk-operations/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-bulk-operations", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Batch processor, CSV/JSON import/export (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/bulk-operations/src/index.ts b/examples/bulk-operations/src/index.ts new file mode 100644 index 0000000..1871ca5 --- /dev/null +++ b/examples/bulk-operations/src/index.ts @@ -0,0 +1,86 @@ +// index.ts - Batch processor, CSV/JSON import/export +// Run: pnpm start +// Requires Neo4j + +import { writeFileSync } from 'node:fs'; +import { GraphClient } from '@graph-kit/sdk'; +import { + createBatchProcessor, + exportToCSV, + exportToJSON, + importFromJSON, +} from '@graph-kit/sdk/batch'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'bulk-' DETACH DELETE n"); + + const users = [ + { id: 'bulk-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + { id: 'bulk-bob', name: 'Bob', email: 'bob@example.com', age: 32 }, + { id: 'bulk-carol', name: 'Carol', email: 'carol@example.com', age: 25 }, + { id: 'bulk-dave', name: 'Dave', email: 'dave@example.com', age: 30 }, + { id: 'bulk-eve', name: 'Eve', email: 'eve@example.com', age: 27 }, + ]; + + console.log('--- Batch processor ---'); + const processor = createBatchProcessor({ driver }); + const result = await processor.bulkInsert({ + label: 'User', + data: users, + onProgress: (p) => console.log(` processed ${p.processed}/${p.total}`), + }); + console.log( + 'bulk insert:', + result.successful.length, + 'successful,', + result.failed.length, + 'failed', + ); + console.log('total users:', await client.count('User')); + + console.log('\n--- Export to JSON ---'); + const allUsers = await client.findMany('User', { limit: 10 }); + const json = exportToJSON(allUsers); + console.log('exported JSON (first 200 chars):', json.slice(0, 200)); + + console.log('\n--- Import from JSON (temp file) ---'); + const tmpFile = '/tmp/bulk-import-users.json'; + writeFileSync(tmpFile, json); + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'bulk-import-' DETACH DELETE n"); + const imported = await importFromJSON({ label: 'User', filePath: tmpFile }); + for (const u of imported.successful) { + await client.create('User', { + data: { ...(u as UserRow), id: `bulk-import-${String(u.id)}` }, + }); + } + console.log('imported users:', imported.successful.length); + console.log('total users now:', await client.count('User')); + + console.log('\n--- Export to CSV ---'); + const csv = exportToCSV(allUsers, { delimiter: ',' }); + console.log('exported CSV:'); + console.log(csv); + + console.log('\nBulk operations example complete.'); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/bulk-operations/src/schema.ts b/examples/bulk-operations/src/schema.ts new file mode 100644 index 0000000..f9170c3 --- /dev/null +++ b/examples/bulk-operations/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Bulk operations example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/bulk-operations/tsconfig.json b/examples/bulk-operations/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/bulk-operations/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/bulk-operations/vitest.config.ts b/examples/bulk-operations/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/bulk-operations/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/configuration/.env.example b/examples/configuration/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/configuration/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/configuration/graph.config.ts b/examples/configuration/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/configuration/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/configuration/package.json b/examples/configuration/package.json new file mode 100644 index 0000000..335ac41 --- /dev/null +++ b/examples/configuration/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-configuration", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "defineConfig, env, loadConfig (no database required)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/configuration/src/index.ts b/examples/configuration/src/index.ts new file mode 100644 index 0000000..beb632b --- /dev/null +++ b/examples/configuration/src/index.ts @@ -0,0 +1,55 @@ +// index.ts - defineConfig, env, loadConfig +// Run: pnpm start +// Does NOT require a database. + +import { defineConfig, env, loadConfig } from '@graph-kit/sdk'; + +// --------------------------------------------------------------------------- +// defineConfig: build a Graph-Kit config object programmatically +// --------------------------------------------------------------------------- + +const config = defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', + }, + debug: true, +}); + +console.log('--- defineConfig ---'); +console.log(' schema:', config.schema); +console.log(' output.directory:', config.output!.directory); +console.log(' output.zod:', config.output!.zod); +console.log(' driver.type:', config.driver!.type); +console.log(' debug:', config.debug); + +// --------------------------------------------------------------------------- +// env: typed environment variable access +// --------------------------------------------------------------------------- + +console.log('\n--- env ---'); +console.log(' NEO4J_URI:', env.NEO4J_URI ?? '(not set)'); +console.log(' NEO4J_USER:', env.NEO4J_USER ?? '(not set)'); +console.log(' NEO4J_PASSWORD:', env.NEO4J_PASSWORD ? '****' : '(not set)'); + +// --------------------------------------------------------------------------- +// loadConfig: load config from a config file path +// --------------------------------------------------------------------------- + +console.log('\n--- loadConfig ---'); +const loaded = await loadConfig('./graph.config.ts'); +if (loaded) { + console.log(' loaded schema:', loaded.schema); + console.log(' loaded driver type:', loaded.driver!.type); +} else { + console.log(' no config file found (skipped)'); +} + +console.log('\nConfiguration example complete (no database required).'); diff --git a/examples/configuration/src/schema.ts b/examples/configuration/src/schema.ts new file mode 100644 index 0000000..6397f2c --- /dev/null +++ b/examples/configuration/src/schema.ts @@ -0,0 +1,10 @@ +// schema.ts - Configuration example schema +import { node, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .build(); + +export const graph = sch().add('User', User).build(); diff --git a/examples/configuration/tsconfig.json b/examples/configuration/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/configuration/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/configuration/vitest.config.ts b/examples/configuration/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/configuration/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/crud-operations/.env.example b/examples/crud-operations/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/crud-operations/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/crud-operations/graph.config.ts b/examples/crud-operations/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/crud-operations/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/crud-operations/package.json b/examples/crud-operations/package.json new file mode 100644 index 0000000..0e754b5 --- /dev/null +++ b/examples/crud-operations/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-crud-operations", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Create, read, update, delete, upsert (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/crud-operations/src/index.ts b/examples/crud-operations/src/index.ts new file mode 100644 index 0000000..d9bb33b --- /dev/null +++ b/examples/crud-operations/src/index.ts @@ -0,0 +1,98 @@ +// index.ts - Create, read, update, delete, upsert +// Run: pnpm start +// Requires Neo4j (docker compose up -d) + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type PostRow, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'crud-' DETACH DELETE n"); + + // --- Create --- + console.log('--- Create ---'); + const alice = await client.create('User', { + data: { id: 'crud-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + }); + const bob = await client.create('User', { + data: { id: 'crud-bob', name: 'Bob', email: 'bob@example.com', age: 32 }, + }); + console.log('created users:', alice.name, bob.name); + + const post = await client.create('Post', { + data: { + id: 'crud-post-1', + title: 'Graph Databases 101', + content: 'Intro to graphs', + published: true, + }, + }); + console.log('created post:', post.title); + + // --- Read --- + console.log('\n--- Read ---'); + const found = await client.findUnique('User', { where: { id: 'crud-alice' } }); + console.log('findUnique:', found?.name, 'age', found?.age); + + const byEmail = await client.findUnique('User', { + where: { email: 'bob@example.com' }, + }); + console.log('find by email:', byEmail?.name); + + const all = await client.findMany('User', { limit: 10 }); + console.log('findMany count:', all.length); + + // --- Update --- + console.log('\n--- Update ---'); + const updated = await client.update('User', { + where: { id: 'crud-alice' }, + data: { age: 29 }, + }); + console.log('updated alice age:', updated.age); + + // --- Upsert --- + console.log('\n--- Upsert ---'); + const upserted = await client.upsert('User', { + where: { id: 'crud-carol' }, + create: { id: 'crud-carol', name: 'Carol', email: 'carol@example.com' }, + update: { name: 'Carol Updated' }, + }); + console.log('upserted:', upserted.name); + + const upsertedAgain = await client.upsert('User', { + where: { id: 'crud-carol' }, + create: { id: 'crud-carol', name: 'Carol', email: 'carol@example.com' }, + update: { age: 31 }, + }); + console.log('upsert again (updated):', upsertedAgain.name, 'age', upsertedAgain.age); + + // --- Count --- + console.log('\n--- Count ---'); + console.log('total users:', await client.count('User')); + console.log('adults:', await client.count('User', { age: { gte: 30 } })); + + // --- Delete --- + console.log('\n--- Delete ---'); + await client.delete('User', { where: { id: 'crud-carol' } }); + const gone = await client.findUnique('User', { where: { id: 'crud-carol' } }); + console.log('carol after delete:', gone); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/crud-operations/src/schema.ts b/examples/crud-operations/src/schema.ts new file mode 100644 index 0000000..b7036bd --- /dev/null +++ b/examples/crud-operations/src/schema.ts @@ -0,0 +1,37 @@ +// schema.ts - CRUD example schema +import { date, node, number, relation, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('content', string({ nullable: true })) + .add('published', { type: 'boolean', default: false }) + .add('createdAt', date({ default: () => new Date() })) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + content: string | null; + published: boolean; + createdAt: Date; +}; diff --git a/examples/crud-operations/tsconfig.json b/examples/crud-operations/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/crud-operations/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/crud-operations/vitest.config.ts b/examples/crud-operations/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/crud-operations/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/error-handling/.env.example b/examples/error-handling/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/error-handling/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/error-handling/graph.config.ts b/examples/error-handling/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/error-handling/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/error-handling/package.json b/examples/error-handling/package.json new file mode 100644 index 0000000..f25835b --- /dev/null +++ b/examples/error-handling/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-error-handling", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "hasCode, isRetryable, toPublic (no database required)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/error-handling/src/index.ts b/examples/error-handling/src/index.ts new file mode 100644 index 0000000..9ba079f --- /dev/null +++ b/examples/error-handling/src/index.ts @@ -0,0 +1,72 @@ +// index.ts - hasCode, isRetryable, toPublic +// Run: pnpm start +// Does NOT require a database. + +import { GraphError, getRootCause, hasCode, isFrontalError, isRetryable } from '@graph-kit/sdk'; + +// --------------------------------------------------------------------------- +// Construct and inspect typed Graph-Kit errors +// --------------------------------------------------------------------------- + +function inspect(label: string, error: unknown) { + console.log(`\n--- ${label} ---`); + console.log(' isGraphError:', error instanceof GraphError); + console.log(' isFrontalError:', isFrontalError(error)); + console.log(' hasCode("record_not_found"):', hasCode(error, 'record_not_found')); + console.log(' hasCode("invalid_argument"):', hasCode(error, 'invalid_argument')); + console.log(' isRetryable:', isRetryable(error)); + const cause = getRootCause(error) as Error | undefined; + console.log(' root cause:', cause?.message ?? '(none)'); +} + +async function main() { + // A not-found error (typically not retryable) + const notFound = new GraphError('User with id "missing" was not found', { + code: 'record_not_found', + statusCode: 404, + }); + inspect('GraphError record_not_found', notFound); + + // A validation error (not retryable) + const validation = new GraphError('Email is required', { + code: 'invalid_argument', + statusCode: 400, + }); + inspect('GraphError invalid_argument', validation); + + // A transient/database error (retryable) + const transient = new GraphError('connection timed out', { + code: 'transient_failure', + statusCode: 503, + retry: { retryable: true }, + }); + inspect('GraphError transient_failure (retryable)', transient); + + // Wrapping an underlying error preserves the root cause + const wrapped = new GraphError('Failed to create user', { + code: 'query_failed', + statusCode: 500, + cause: new Error('neo4j: socket hang up'), + }); + inspect('GraphError wrapped with cause', wrapped); + + // toPublic - strip internals for client-facing responses + console.log('\n--- toPublic (client-safe shape) ---'); + const publicShape = { + code: notFound.code ?? 'unknown', + message: notFound.message, + statusCode: notFound.statusCode, + retryable: isRetryable(notFound), + }; + console.log(JSON.stringify(publicShape, null, 2)); + + // Plain (non-Graph-Kit) errors still inspect safely + inspect('plain Error', new Error('something went wrong')); + + console.log('\nError handling example complete (no database required).'); +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/error-handling/src/schema.ts b/examples/error-handling/src/schema.ts new file mode 100644 index 0000000..30c74ed --- /dev/null +++ b/examples/error-handling/src/schema.ts @@ -0,0 +1,10 @@ +// schema.ts - Error handling example schema +import { node, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .build(); + +export const graph = sch().add('User', User).build(); diff --git a/examples/error-handling/tsconfig.json b/examples/error-handling/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/error-handling/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/error-handling/vitest.config.ts b/examples/error-handling/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/error-handling/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/graphql-schema/.env.example b/examples/graphql-schema/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/graphql-schema/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/graphql-schema/graph.config.ts b/examples/graphql-schema/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/graphql-schema/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/graphql-schema/package.json b/examples/graphql-schema/package.json new file mode 100644 index 0000000..47d149f --- /dev/null +++ b/examples/graphql-schema/package.json @@ -0,0 +1,26 @@ +{ + "name": "example-graphql-schema", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Generate GraphQL SDL + resolvers (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@apollo/server": "^5.5.1", + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/graphql-schema/src/index.ts b/examples/graphql-schema/src/index.ts new file mode 100644 index 0000000..3905d46 --- /dev/null +++ b/examples/graphql-schema/src/index.ts @@ -0,0 +1,65 @@ +// index.ts - Generate GraphQL SDL and resolvers from the schema +// Run: pnpm start +// Requires Neo4j (only to exercise resolvers; SDL generation needs no DB) + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { generateGraphQLSchema, generateResolvers } from '@graph-kit/sdk/graphql'; +import { graph } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +type Resolver = (parent: unknown, args: Record) => Promise; +type ResolverMap = { + Query: Record; + Mutation: Record; +}; + +function resolver(map: Record, name: string): Resolver { + const fn = map[name]; + if (!fn) throw new Error(`No resolver named ${name}`); + return fn; +} + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + // 1. The schema definition language for the current graph schema + const sdl = generateGraphQLSchema({ schema: graph, includeRelations: true }); + console.log('--- Generated SDL ---'); + console.log(sdl); + + // 2. Resolvers backed by the client + const resolvers = generateResolvers({ schema: graph, client }) as unknown as ResolverMap; + + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'gql-' DETACH DELETE n"); + + const created = await resolver(resolvers.Mutation, 'createUser')(null, { + data: { id: 'gql-dana', name: 'Dana', email: 'dana@gql.example', age: 27 }, + }); + console.log('\nMutation createUser ->', (created as { name: string }).name); + + const found = await resolver(resolvers.Query, 'user')(null, { + where: { id: 'gql-dana' }, + }); + console.log('Query user ->', (found as { name: string } | null)?.name); + + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'gql-' DETACH DELETE n"); + } finally { + await driver.disconnect(); + } + + console.log('\nGraphQL schema example complete.'); +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/graphql-schema/src/schema.ts b/examples/graphql-schema/src/schema.ts new file mode 100644 index 0000000..41b29b2 --- /dev/null +++ b/examples/graphql-schema/src/schema.ts @@ -0,0 +1,39 @@ +// schema.ts - GraphQL schema example schema +import { date, node, number, relation, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .add('posts', relation('POSTED', 'OUT', 'Post', { multiple: true })) + .index(['email'], true) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('content', string({ nullable: true })) + .add('published', { type: 'boolean', default: false }) + .add('createdAt', date({ default: () => new Date() })) + .add('author', relation('POSTED', 'IN', 'User')) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + content: string | null; + published: boolean; + createdAt: Date; +}; diff --git a/examples/graphql-schema/tsconfig.json b/examples/graphql-schema/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/graphql-schema/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/graphql-schema/vitest.config.ts b/examples/graphql-schema/vitest.config.ts new file mode 100644 index 0000000..99db6a0 --- /dev/null +++ b/examples/graphql-schema/vitest.config.ts @@ -0,0 +1,16 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + '@graph-kit/sdk/graphql': path.resolve(__dirname, '../../packages/sdk/src/graphql/index.ts'), + }, + }, +}); diff --git a/examples/migrations/.env.example b/examples/migrations/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/migrations/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/migrations/graph.config.ts b/examples/migrations/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/migrations/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/migrations/migrations/20240115143000_initial_schema.ts b/examples/migrations/migrations/20240115143000_initial_schema.ts new file mode 100644 index 0000000..00a4038 --- /dev/null +++ b/examples/migrations/migrations/20240115143000_initial_schema.ts @@ -0,0 +1,33 @@ +// 20240115143000_initial_schema.ts +// Initial schema migration - creates constraints and indexes + +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; + +export const migration: Migration = { + version: '20240115143000', + name: 'initial_schema', + timestamp: 1705329000000, + + up: (_compiler: QueryCompiler) => { + return [ + 'CREATE CONSTRAINT user_id_unique IF NOT EXISTS FOR (u:User) REQUIRE u.id IS UNIQUE', + 'CREATE CONSTRAINT user_email_unique IF NOT EXISTS FOR (u:User) REQUIRE u.email IS UNIQUE', + 'CREATE INDEX user_email_index IF NOT EXISTS FOR (u:User) ON (u.email)', + 'CREATE INDEX user_name_index IF NOT EXISTS FOR (u:User) ON (u.name)', + 'CREATE INDEX user_age_index IF NOT EXISTS FOR (u:User) ON (u.age)', + 'CREATE INDEX user_createdat_index IF NOT EXISTS FOR (u:User) ON (u.createdAt)', + ]; + }, + + down: (_compiler: QueryCompiler) => { + return [ + 'DROP INDEX user_createdat_index IF EXISTS', + 'DROP INDEX user_age_index IF EXISTS', + 'DROP INDEX user_name_index IF EXISTS', + 'DROP INDEX user_email_index IF EXISTS', + 'DROP CONSTRAINT user_email_unique IF EXISTS', + 'DROP CONSTRAINT user_id_unique IF EXISTS', + ]; + }, +}; diff --git a/examples/migrations/migrations/20240116100000_add_user_bio.ts b/examples/migrations/migrations/20240116100000_add_user_bio.ts new file mode 100644 index 0000000..cc23559 --- /dev/null +++ b/examples/migrations/migrations/20240116100000_add_user_bio.ts @@ -0,0 +1,19 @@ +// 20240116100000_add_user_bio.ts +// Adds a bio index to User + +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; + +export const migration: Migration = { + version: '20240116100000', + name: 'add_user_bio', + timestamp: 1705392000000, + + up: (_compiler: QueryCompiler) => { + return ['CREATE INDEX user_bio_index IF NOT EXISTS FOR (u:User) ON (u.bio)']; + }, + + down: (_compiler: QueryCompiler) => { + return ['DROP INDEX user_bio_index IF EXISTS']; + }, +}; diff --git a/examples/migrations/package.json b/examples/migrations/package.json new file mode 100644 index 0000000..36689fa --- /dev/null +++ b/examples/migrations/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-migrations", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Migration runner: up, status, rollback (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/migrations/src/index.ts b/examples/migrations/src/index.ts new file mode 100644 index 0000000..c690610 --- /dev/null +++ b/examples/migrations/src/index.ts @@ -0,0 +1,62 @@ +// index.ts - Migration runner: up, status, rollback +// Run: pnpm start +// Requires Neo4j + +import type { DriverAdapter } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import type { Migration } from '@graph-kit/sdk/migration'; +import { createMigrationRunner } from '@graph-kit/sdk/migration'; +import { migration as initialSchema } from '../migrations/20240115143000_initial_schema.js'; +import { migration as addUserBio } from '../migrations/20240116100000_add_user_bio.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +const migrations: Migration[] = [initialSchema, addUserBio]; + +async function printStatus(runner: ReturnType, label: string) { + const statuses = await runner.status(migrations); + console.log(`\n${label}`); + for (const status of statuses) { + console.log(` ${status.applied ? '[x]' : '[ ]'} ${status.version} ${status.name}`); + } +} + +async function main() { + await driver.connect(); + const runner = createMigrationRunner({ + driver: driver as DriverAdapter, + schema: undefined, + }); + + await printStatus(runner, 'Before applying migrations:'); + + console.log('\n--- Applying pending migrations ---'); + for (const migration of migrations) { + await runner.applyMigration(migration); + console.log(` applied ${migration.version} ${migration.name}`); + } + + await printStatus(runner, 'After applying migrations:'); + + console.log('\n--- Rolling back is not supported by the runner (use each migration down) ---'); + // Demonstrate the down() of the last migration directly + const down = migrations[migrations.length - 1]?.down; + if (down) { + const statements = down(undefined as unknown as never); + console.log(' last migration down statements:', statements.length); + } + + await printStatus(runner, 'Final status:'); + + await driver.disconnect(); +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/migrations/src/schema.ts b/examples/migrations/src/schema.ts new file mode 100644 index 0000000..8d17898 --- /dev/null +++ b/examples/migrations/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Migrations example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/migrations/tsconfig.json b/examples/migrations/tsconfig.json new file mode 100644 index 0000000..212a916 --- /dev/null +++ b/examples/migrations/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "migrations", "graph.config.ts"] +} diff --git a/examples/migrations/vitest.config.ts b/examples/migrations/vitest.config.ts new file mode 100644 index 0000000..ddf8715 --- /dev/null +++ b/examples/migrations/vitest.config.ts @@ -0,0 +1,19 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + '@graph-kit/sdk/migration': path.resolve( + __dirname, + '../../packages/sdk/src/migration/index.ts', + ), + }, + }, +}); diff --git a/examples/mock-driver-testing/.env.example b/examples/mock-driver-testing/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/mock-driver-testing/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/mock-driver-testing/graph.config.ts b/examples/mock-driver-testing/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/mock-driver-testing/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/mock-driver-testing/package.json b/examples/mock-driver-testing/package.json new file mode 100644 index 0000000..c5915dc --- /dev/null +++ b/examples/mock-driver-testing/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-mock-driver-testing", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Unit testing without a database (mock driver) (no database required)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/mock-driver-testing/src/index.ts b/examples/mock-driver-testing/src/index.ts new file mode 100644 index 0000000..8daa7e4 --- /dev/null +++ b/examples/mock-driver-testing/src/index.ts @@ -0,0 +1,55 @@ +// index.ts - Unit testing without a database (mock driver) +// Run: pnpm start +// Does NOT require a database. + +import { GraphClient } from '@graph-kit/sdk'; +import { createMockDriver } from '@graph-kit/sdk/testing'; +import { graph, type UserRow } from './schema.js'; + +async function main() { + // The mock driver stores everything in memory — no Neo4j needed. + const driver = createMockDriver(); + const client = new GraphClient(driver, graph); + + console.log('--- Create (mock) ---'); + const alice = await client.create('User', { + data: { id: 'mock-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + }); + console.log('created:', alice.name); + + console.log('\n--- Find unique (mock) ---'); + const found = await client.findUnique('User', { where: { id: 'mock-alice' } }); + console.log('findUnique:', found?.name, 'age', found?.age); + + console.log('\n--- Find many with filter (mock) ---'); + const adults = await client.findMany('User', { + where: { age: { gte: 18 } }, + }); + console.log('adults:', adults.map((u) => u.name).join(', ')); + + console.log('\n--- Count (mock) ---'); + console.log('total users:', await client.count('User')); + + console.log('\n--- Update (mock) ---'); + const updated = await client.update('User', { + where: { id: 'mock-alice' }, + data: { age: 29 }, + }); + console.log('updated alice age:', updated.age); + + console.log('\n--- Delete (mock) ---'); + await client.delete('User', { where: { id: 'mock-alice' } }); + const gone = await client.findUnique('User', { where: { id: 'mock-alice' } }); + console.log('alice after delete:', gone); + + console.log('\n--- Raw query (mock) ---'); + const all = await client.raw<{ name: string }>('MATCH (u:User) RETURN u.name AS name'); + console.log('all names:', all.map((r) => r.name).join(', ')); + + console.log('\nMock driver testing example complete (no database required).'); +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/mock-driver-testing/src/schema.ts b/examples/mock-driver-testing/src/schema.ts new file mode 100644 index 0000000..55c7e97 --- /dev/null +++ b/examples/mock-driver-testing/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Mock driver testing example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/mock-driver-testing/tsconfig.json b/examples/mock-driver-testing/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/mock-driver-testing/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/mock-driver-testing/vitest.config.ts b/examples/mock-driver-testing/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/mock-driver-testing/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/multi-driver/.env.example b/examples/multi-driver/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/multi-driver/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/multi-driver/graph.config.ts b/examples/multi-driver/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/multi-driver/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/multi-driver/package.json b/examples/multi-driver/package.json new file mode 100644 index 0000000..71d0ce6 --- /dev/null +++ b/examples/multi-driver/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-multi-driver", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Switch between Neo4j, Memgraph, FalkorDB (Neo4j requires DB)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/multi-driver/src/index.ts b/examples/multi-driver/src/index.ts new file mode 100644 index 0000000..ca59e64 --- /dev/null +++ b/examples/multi-driver/src/index.ts @@ -0,0 +1,85 @@ +// index.ts - Switch between Neo4j, Memgraph, FalkorDB +// Run: pnpm start +// Neo4j requires a running instance; Memgraph/FalkorDB configs are shown for reference. + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type UserRow } from './schema.js'; + +function neo4jConfig() { + return { + type: 'neo4j' as const, + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', + }; +} + +function memgraphConfig() { + return { + type: 'memgraph' as const, + host: 'localhost', + port: 7687, + username: process.env.MEMGRAPH_USER ?? '', + password: process.env.MEMGRAPH_PASSWORD ?? '', + }; +} + +function falkordbConfig() { + return { + type: 'falkordb' as const, + host: 'localhost', + port: 6379, + username: process.env.FALKORDB_USER ?? '', + password: process.env.FALKORDB_PASSWORD ?? '', + }; +} + +async function runNeo4j() { + console.log('\n=== Neo4j (live) ==='); + const driver = createNeo4jDriver(neo4jConfig()); + await driver.connect(); + const client = new GraphClient(driver, graph); + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'multi-' DETACH DELETE n"); + + const alice = await client.create('User', { + data: { id: 'multi-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + }); + console.log('created:', alice.name); + + const found = await client.findUnique('User', { where: { id: 'multi-alice' } }); + console.log('findUnique:', found?.name, 'age', found?.age); + } finally { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'multi-' DETACH DELETE n"); + await driver.disconnect(); + } +} + +async function main() { + console.log('--- Multi-driver: Neo4j (live) ---'); + await runNeo4j(); + + console.log('\n--- Multi-driver: Memgraph (config only) ---'); + console.log('config:', JSON.stringify(memgraphConfig())); + console.log( + '(configure MEMGRAPH_USER / MEMGRAPH_PASSWORD and connect with createMemgraphDriver to run)', + ); + + console.log('\n--- Multi-driver: FalkorDB (config only) ---'); + console.log('config:', JSON.stringify(falkordbConfig())); + console.log( + '(configure FALKORDB_USER / FALKORDB_PASSWORD and connect with createFalkorDBDriver to run)', + ); + + console.log('\n--- createDriver registry ---'); + const { createDriver } = await import('@graph-kit/sdk/driver'); + console.log('drivers available via the createDriver() factory'); + + console.log('\nMulti-driver example complete.'); +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/multi-driver/src/schema.ts b/examples/multi-driver/src/schema.ts new file mode 100644 index 0000000..3240d4f --- /dev/null +++ b/examples/multi-driver/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Multi-driver example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/multi-driver/tsconfig.json b/examples/multi-driver/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/multi-driver/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/multi-driver/vitest.config.ts b/examples/multi-driver/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/multi-driver/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/observability/.env.example b/examples/observability/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/observability/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/observability/graph.config.ts b/examples/observability/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/observability/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/observability/package.json b/examples/observability/package.json new file mode 100644 index 0000000..50727c4 --- /dev/null +++ b/examples/observability/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-observability", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Query logging, metrics, profiling (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/observability/src/index.ts b/examples/observability/src/index.ts new file mode 100644 index 0000000..d0b7b2d --- /dev/null +++ b/examples/observability/src/index.ts @@ -0,0 +1,69 @@ +// index.ts - Query logging, metrics, profiling +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { + createQueryLogger, + createQueryProfiler, + LoggingDriverAdapter, + PrometheusMetricsCollector, +} from '@graph-kit/sdk/observability'; +import { graph, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'obs-' DETACH DELETE n"); + + // Query logger: prints every Cypher statement and its params. + const queryLogger = createQueryLogger({ enabled: true }); + const loggedDriver = new LoggingDriverAdapter(driver, queryLogger); + const loggedClient = new GraphClient(loggedDriver, graph); + + await loggedClient.create('User', { + data: { id: 'obs-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + }); + + await loggedClient.findUnique('User', { where: { id: 'obs-alice' } }); + + // Query profiler: run EXPLAIN/PROFILE on a statement. + const profiler = createQueryProfiler(driver); + const explain = await profiler.explain('MATCH (u:User) WHERE u.id = $id RETURN u', { + id: 'obs-alice', + }); + console.log('\n--- Profiled EXPLAIN ---'); + console.log(' operator:', explain.plan.operatorType); + console.log(' estimated rows:', explain.plan.estimatedRows); + + // Metrics collector (Prometheus-compatible) - expose counters/histograms. + const metrics = new PrometheusMetricsCollector(); + metrics.incrementCounter('graph_kit_queries_total', { operation: 'create' }); + metrics.incrementCounter('graph_kit_queries_total', { operation: 'find' }); + metrics.recordHistogram('graph_kit_query_duration_ms', 12.5); + + console.log('\n--- Prometheus metrics sample ---'); + console.log(metrics.getMetrics()); + + console.log('\nObservability example complete.'); + } finally { + await driver.disconnect(); + } +} + +// Declared after main so it's hoisted; used inside main above. +const client = new GraphClient(driver, graph); + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/observability/src/schema.ts b/examples/observability/src/schema.ts new file mode 100644 index 0000000..da896ac --- /dev/null +++ b/examples/observability/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Observability example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/observability/tsconfig.json b/examples/observability/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/observability/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/observability/vitest.config.ts b/examples/observability/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/observability/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/pagination/.env.example b/examples/pagination/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/pagination/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/pagination/graph.config.ts b/examples/pagination/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/pagination/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/pagination/package.json b/examples/pagination/package.json new file mode 100644 index 0000000..7cc8df8 --- /dev/null +++ b/examples/pagination/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-pagination", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Offset/limit and cursor pagination (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/pagination/src/index.ts b/examples/pagination/src/index.ts new file mode 100644 index 0000000..bc3323b --- /dev/null +++ b/examples/pagination/src/index.ts @@ -0,0 +1,70 @@ +// index.ts - Offset/limit and cursor pagination +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'pg-' DETACH DELETE n"); + + for (let i = 1; i <= 6; i++) { + await client.create('User', { + data: { id: `pg-user-${i}`, name: `User ${i}`, email: `user${i}@example.com`, age: 20 + i }, + }); + } + + console.log('--- offset/limit pagination ---'); + const page1 = await client.findMany('User', { + limit: 2, + orderBy: { name: 'asc' }, + }); + console.log('page 1:', page1.map((u) => u.name).join(', ')); + + const page2 = await client.findMany('User', { + limit: 2, + skip: 2, + orderBy: { name: 'asc' }, + }); + console.log('page 2:', page2.map((u) => u.name).join(', ')); + + const page3 = await client.findMany('User', { + limit: 2, + skip: 4, + orderBy: { name: 'asc' }, + }); + console.log('page 3:', page3.map((u) => u.name).join(', ')); + + console.log('\n--- cursor-based pagination (skip after last seen page) ---'); + const first = await client.findMany('User', { + limit: 2, + orderBy: { name: 'asc' }, + }); + const next = await client.findMany('User', { + limit: 2, + skip: 2, + orderBy: { name: 'asc' }, + }); + console.log('first page:', first.map((u) => u.name).join(', ')); + console.log('next page:', next.map((u) => u.name).join(', ')); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/pagination/src/schema.ts b/examples/pagination/src/schema.ts new file mode 100644 index 0000000..40bdec9 --- /dev/null +++ b/examples/pagination/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Pagination example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/pagination/tsconfig.json b/examples/pagination/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/pagination/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/pagination/vitest.config.ts b/examples/pagination/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/pagination/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/path-traversal/.env.example b/examples/path-traversal/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/path-traversal/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/path-traversal/graph.config.ts b/examples/path-traversal/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/path-traversal/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/path-traversal/package.json b/examples/path-traversal/package.json new file mode 100644 index 0000000..a5ae25b --- /dev/null +++ b/examples/path-traversal/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-path-traversal", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "traverse(), shortestPath(), allShortestPaths() (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/path-traversal/src/index.ts b/examples/path-traversal/src/index.ts new file mode 100644 index 0000000..e47cd38 --- /dev/null +++ b/examples/path-traversal/src/index.ts @@ -0,0 +1,70 @@ +// index.ts - traverse(), shortestPath(), allShortestPaths() +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'pt-' DETACH DELETE n"); + + const users = [ + { id: 'pt-alice', name: 'Alice' }, + { id: 'pt-bob', name: 'Bob' }, + { id: 'pt-carol', name: 'Carol' }, + { id: 'pt-dave', name: 'Dave' }, + { id: 'pt-eve', name: 'Eve' }, + ]; + for (const u of users) { + await client.create('User', { data: u }); + } + + // Alice -> Bob -> Carol -> Dave, and Bob -> Eve + await client.relate('User', 'pt-alice', 'FOLLOWS', 'User', 'pt-bob'); + await client.relate('User', 'pt-bob', 'FOLLOWS', 'User', 'pt-carol'); + await client.relate('User', 'pt-carol', 'FOLLOWS', 'User', 'pt-dave'); + await client.relate('User', 'pt-bob', 'FOLLOWS', 'User', 'pt-eve'); + + console.log('--- traverse (variable-length path) ---'); + const network = await client.traverse('User', 'FOLLOWS', 'User', { + fromId: 'pt-alice', + maxDepth: 3, + }); + console.log("Alice's network (up to 3 hops):", network.map((n) => String(n.name)).join(' -> ')); + + console.log('\n--- shortestPath ---'); + const shortest = await client.findShortestPath('User', 'FOLLOWS', 'User', { + fromId: 'pt-alice', + toId: 'pt-dave', + maxDepth: 5, + }); + console.log('shortest path Alice->Dave:', shortest ? 'found' : 'not found'); + + console.log('\n--- allShortestPaths ---'); + const all = await client.findAllShortestPaths('User', 'FOLLOWS', 'User', { + fromId: 'pt-alice', + toId: 'pt-dave', + maxDepth: 5, + }); + console.log(`all shortest paths Alice->Dave: ${all.length} path(s)`); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/path-traversal/src/schema.ts b/examples/path-traversal/src/schema.ts new file mode 100644 index 0000000..cbbf1f7 --- /dev/null +++ b/examples/path-traversal/src/schema.ts @@ -0,0 +1,18 @@ +// schema.ts - Path traversal example schema +import { date, node, relation, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('createdAt', date({ default: () => new Date() })) + .add('following', relation('FOLLOWS', 'OUT', 'User', { multiple: true })) + .add('followers', relation('FOLLOWS', 'IN', 'User', { multiple: true })) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + createdAt: Date; +}; diff --git a/examples/path-traversal/tsconfig.json b/examples/path-traversal/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/path-traversal/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/path-traversal/vitest.config.ts b/examples/path-traversal/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/path-traversal/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/query-filters/.env.example b/examples/query-filters/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/query-filters/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/query-filters/graph.config.ts b/examples/query-filters/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/query-filters/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/query-filters/package.json b/examples/query-filters/package.json new file mode 100644 index 0000000..a65eb3a --- /dev/null +++ b/examples/query-filters/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-query-filters", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Where clauses, operators, AND/OR/NOT (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/query-filters/src/index.ts b/examples/query-filters/src/index.ts new file mode 100644 index 0000000..ca1a54f --- /dev/null +++ b/examples/query-filters/src/index.ts @@ -0,0 +1,72 @@ +// index.ts - Where clauses, operators, AND/OR/NOT +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'qf-' DETACH DELETE n"); + + const users = [ + { id: 'qf-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + { id: 'qf-bob', name: 'Bob', email: 'bob@example.com', age: 32 }, + { id: 'qf-carol', name: 'Carol', email: 'carol@example.com', age: 25 }, + { id: 'qf-dave', name: 'Dave', email: 'dave@example.com', age: 30 }, + ]; + for (const u of users) { + await client.create('User', { data: u }); + } + + console.log('--- Comparison operators ---'); + const adults = await client.findMany('User', { + where: { age: { gte: 18, lte: 32 } }, + orderBy: { age: 'desc' }, + }); + console.log('age 18-32 desc:', adults.map((u) => `${u.name}(${u.age})`).join(', ')); + + console.log('\n--- Equality / IN / contains ---'); + const byEmails = await client.findMany('User', { + where: { email: { in: ['alice@example.com', 'dave@example.com'] } }, + }); + console.log('in emails:', byEmails.map((u) => u.name).join(', ')); + + const containsA = await client.findMany('User', { + where: { name: { contains: 'a' } }, + }); + console.log('name contains "a":', containsA.map((u) => u.name).join(', ')); + + console.log('\n--- AND / OR / NOT ---'); + const andOr = await client.findMany('User', { + where: { + AND: [{ age: { gte: 25 } }, { OR: [{ name: 'Alice' }, { name: 'Dave' }] }], + }, + }); + console.log('age>=25 AND (Alice OR Dave):', andOr.map((u) => u.name).join(', ')); + + const notYoung = await client.findMany('User', { + where: { NOT: { age: { lt: 30 } } }, + orderBy: { name: 'asc' }, + }); + console.log('NOT age<30:', notYoung.map((u) => u.name).join(', ')); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/query-filters/src/schema.ts b/examples/query-filters/src/schema.ts new file mode 100644 index 0000000..209b3de --- /dev/null +++ b/examples/query-filters/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Query filters example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/query-filters/tsconfig.json b/examples/query-filters/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/query-filters/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/query-filters/vitest.config.ts b/examples/query-filters/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/query-filters/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/raw-cypher/.env.example b/examples/raw-cypher/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/raw-cypher/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/raw-cypher/graph.config.ts b/examples/raw-cypher/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/raw-cypher/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/raw-cypher/package.json b/examples/raw-cypher/package.json new file mode 100644 index 0000000..b8b5bee --- /dev/null +++ b/examples/raw-cypher/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-raw-cypher", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Raw queries with parameters (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/raw-cypher/src/index.ts b/examples/raw-cypher/src/index.ts new file mode 100644 index 0000000..cb8dc89 --- /dev/null +++ b/examples/raw-cypher/src/index.ts @@ -0,0 +1,71 @@ +// index.ts - Raw queries with parameters +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type PostRow, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'raw-' DETACH DELETE n"); + + await client.create('User', { + data: { id: 'raw-alice', name: 'Alice', email: 'alice@example.com', age: 28 }, + }); + await client.create('User', { + data: { id: 'raw-bob', name: 'Bob', email: 'bob@example.com', age: 32 }, + }); + await client.create('Post', { + data: { id: 'raw-post-1', title: 'Graph Databases 101', published: true }, + }); + await client.create('Post', { + data: { id: 'raw-post-2', title: 'Cypher Tips', published: true }, + }); + await client.relate('User', 'raw-alice', 'POSTED', 'Post', 'raw-post-1', 'IN'); + await client.relate('User', 'raw-bob', 'POSTED', 'Post', 'raw-post-2', 'IN'); + await client.relate('User', 'raw-bob', 'LIKES', 'Post', 'raw-post-1'); + + console.log('--- raw query ---'); + const follows = await client.raw<{ follower: string; followed: string }>( + 'MATCH (u:User)-[:FOLLOWS]->(f:User) RETURN u.name AS follower, f.name AS followed', + ); + for (const row of follows) { + console.log(` ${row.follower} follows ${row.followed}`); + } + + console.log('\n--- raw query with parameters ---'); + const postCount = await client.raw<{ name: string; postCount: number }>( + 'MATCH (u:User {id: $id})-[:POSTED]->(p:Post) RETURN u.name AS name, count(p) AS postCount', + { id: 'raw-alice' }, + ); + console.log(`alice post count: ${postCount[0]?.postCount}`); + + console.log('\n--- raw write via parameters ---'); + await client.raw('CREATE (u:User {id: $id, name: $name, email: $email, age: $age})', { + id: 'raw-dana', + name: 'Dana', + email: 'dana@example.com', + age: 27, + }); + const dana = await client.findUnique('User', { where: { id: 'raw-dana' } }); + console.log('created via raw:', dana?.name, dana?.age); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/raw-cypher/src/schema.ts b/examples/raw-cypher/src/schema.ts new file mode 100644 index 0000000..e2dcb17 --- /dev/null +++ b/examples/raw-cypher/src/schema.ts @@ -0,0 +1,36 @@ +// schema.ts - Raw Cypher example schema +import { date, node, number, relation, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('published', { type: 'boolean', default: false }) + .add('createdAt', date({ default: () => new Date() })) + .add('author', relation('POSTED', 'IN', 'User')) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + published: boolean; + createdAt: Date; +}; diff --git a/examples/raw-cypher/tsconfig.json b/examples/raw-cypher/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/raw-cypher/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/raw-cypher/vitest.config.ts b/examples/raw-cypher/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/raw-cypher/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/relations/.env.example b/examples/relations/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/relations/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/relations/graph.config.ts b/examples/relations/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/relations/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/relations/package.json b/examples/relations/package.json new file mode 100644 index 0000000..1e90fd5 --- /dev/null +++ b/examples/relations/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-relations", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "relate(), unrelate(), includes (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/relations/src/index.ts b/examples/relations/src/index.ts new file mode 100644 index 0000000..9e448f9 --- /dev/null +++ b/examples/relations/src/index.ts @@ -0,0 +1,85 @@ +// index.ts - relate(), unrelate(), includes +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type PostRow, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'rel-' DETACH DELETE n"); + + const alice = await client.create('User', { + data: { id: 'rel-alice', name: 'Alice', email: 'alice@example.com' }, + }); + const bob = await client.create('User', { + data: { id: 'rel-bob', name: 'Bob', email: 'bob@example.com' }, + }); + const carol = await client.create('User', { + data: { id: 'rel-carol', name: 'Carol', email: 'carol@example.com' }, + }); + const post = await client.create('Post', { + data: { id: 'rel-post-1', title: 'Hello Graph', published: true }, + }); + + console.log('--- relate() ---'); + await client.relate('User', 'rel-alice', 'FOLLOWS', 'User', 'rel-bob'); + await client.relate('User', 'rel-alice', 'FOLLOWS', 'User', 'rel-carol'); + await client.relate('User', 'rel-bob', 'FOLLOWS', 'User', 'rel-carol'); + await client.relate('Post', 'rel-post-1', 'POSTED', 'User', 'rel-alice', 'IN'); + await client.relate('User', 'rel-bob', 'LIKES', 'Post', 'rel-post-1'); + await client.relate('User', 'rel-carol', 'LIKES', 'Post', 'rel-post-1'); + console.log('relationships created'); + + console.log('\n--- includes: posts and author ---'); + const usersWithPosts = await client.findMany('User', { + include: { posts: true }, + limit: 10, + }); + for (const u of usersWithPosts) { + console.log(` ${u.name}: ${u.posts?.map((p) => p.title).join(', ') ?? 'none'}`); + } + + const postsWithAuthor = await client.findMany('Post', { + include: { author: true }, + }); + for (const p of postsWithAuthor) { + console.log(` ${p.title} by ${p.author?.name ?? 'unknown'}`); + } + + const postsWithLikers = await client.findMany('Post', { + where: { id: 'rel-post-1' }, + include: { likedBy: true }, + }); + console.log( + 'post-1 liked by:', + postsWithLikers[0]?.likedBy?.map((u) => u.name).join(', ') ?? 'none', + ); + + console.log('\n--- unrelate() ---'); + await client.unrelate('User', 'rel-alice', 'FOLLOWS', 'User', 'rel-bob'); + const remaining = await client.raw( + 'MATCH (u:User {id: $id})-[:FOLLOWS]->(f:User) RETURN count(*) as count', + { id: 'rel-alice' }, + ); + console.log('alice follows after unrelate bob:', remaining[0]?.count); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/relations/src/schema.ts b/examples/relations/src/schema.ts new file mode 100644 index 0000000..cfba1bd --- /dev/null +++ b/examples/relations/src/schema.ts @@ -0,0 +1,40 @@ +// schema.ts - Relations example schema +import { date, node, relation, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('createdAt', date({ default: () => new Date() })) + .add('posts', relation('POSTED', 'OUT', 'Post', { multiple: true })) + .add('following', relation('FOLLOWS', 'OUT', 'User', { multiple: true })) + .add('likedPosts', relation('LIKES', 'OUT', 'Post', { multiple: true })) + .index(['email'], true) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('content', string({ nullable: true })) + .add('published', { type: 'boolean', default: false }) + .add('createdAt', date({ default: () => new Date() })) + .add('author', relation('POSTED', 'IN', 'User')) + .add('likedBy', relation('LIKES', 'IN', 'User', { multiple: true })) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + content: string | null; + published: boolean; + createdAt: Date; +}; diff --git a/examples/relations/tsconfig.json b/examples/relations/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/relations/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/relations/vitest.config.ts b/examples/relations/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/relations/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/schema-definition/.env.example b/examples/schema-definition/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/schema-definition/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/schema-definition/graph.config.ts b/examples/schema-definition/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/schema-definition/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/schema-definition/package.json b/examples/schema-definition/package.json new file mode 100644 index 0000000..bbe2f55 --- /dev/null +++ b/examples/schema-definition/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-schema-definition", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Schema DSL: nodes, properties, relations, indexes (no database required)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/schema-definition/src/index.ts b/examples/schema-definition/src/index.ts new file mode 100644 index 0000000..d4e3f1c --- /dev/null +++ b/examples/schema-definition/src/index.ts @@ -0,0 +1,137 @@ +// index.ts - Schema DSL: nodes, properties, relations, indexes +// Run: pnpm start +// Does NOT require a database. + +import { + boolean, + date, + defineRel, + json, + node, + number, + relation, + schema as sch, + string, + uuid, +} from '@graph-kit/sdk'; +import type { UserRow } from './schema.js'; + +// --------------------------------------------------------------------------- +// Node definition +// --------------------------------------------------------------------------- + +const User = node('User') + .add('id', string({ primary: true })) // primary key + .add('name', string()) + .add('email', string({ unique: true })) // uniqueness constraint + .add('age', number({ nullable: true })) // nullable + .add('bio', string({ nullable: true, default: '' })) + .add('settings', json({ nullable: true })) // arbitrary JSON + .add('avatarId', uuid({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) // default factory + .add('updatedAt', date({ nullable: true })) + .add('posts', relation('POSTED', 'OUT', 'Post', { multiple: true })) + .add('following', relation('FOLLOWS', 'OUT', 'User', { multiple: true })) + .add('followers', relation('FOLLOWS', 'IN', 'User', { multiple: true })) + .index(['email'], true) // unique index + .index(['createdAt']) // non-unique index + .build(); + +const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('content', string({ nullable: true })) + .add('published', boolean({ default: false })) + .add('tags', string({ array: true })) // array of strings + .add('createdAt', date({ default: () => new Date() })) + .add('viewCount', number({ default: 0 })) + .add('author', relation('POSTED', 'IN', 'User')) + .add('likedBy', relation('LIKES', 'IN', 'User', { multiple: true })) + .index(['title']) + .index(['published']) + .build(); + +// --------------------------------------------------------------------------- +// Relation definitions (standalone relation entities with properties) +// --------------------------------------------------------------------------- + +const AUTHORED = defineRel('AUTHORED', 'OUT', 'Post', { + properties: { + createdAt: date({ default: () => new Date() }), + weight: number({ default: 1 }), + }, +}); + +const FOLLOWS = defineRel('FOLLOWS', 'OUT', 'User', { + properties: { + since: date(), + }, +}); + +// --------------------------------------------------------------------------- +// Schema registry +// --------------------------------------------------------------------------- + +const graph = sch().add('User', User).add('Post', Post).build(); + +// --------------------------------------------------------------------------- +// Inspection (the built registry is the nodes map itself) +// --------------------------------------------------------------------------- + +function describeNode(nodeConfig: { + label: string; + properties: Record; + relations: Record; +}) { + console.log(`Node: ${nodeConfig.label}`); + console.log(' Properties:'); + for (const [name, prop] of Object.entries( + nodeConfig.properties as Record< + string, + { + primary?: boolean; + unique?: boolean; + nullable?: boolean; + array?: boolean; + default?: unknown; + type: string; + } + >, + )) { + const flags = [ + prop.primary ? 'PK' : '', + prop.unique ? 'UNIQUE' : '', + prop.nullable ? 'NULLABLE' : '', + prop.array ? 'ARRAY' : '', + prop.default !== undefined ? 'DEFAULT' : '', + ] + .filter(Boolean) + .join(' '); + console.log(` ${name}: ${prop.type}${flags ? ` (${flags})` : ''}`); + } + + console.log(' Relations:'); + for (const [name, rel] of Object.entries( + nodeConfig.relations as Record, + )) { + console.log(` ${name}: ${rel.type} -> ${rel.target} (${rel.direction})`); + } +} + +describeNode(User); +describeNode(Post); + +console.log('\nSchema nodes:', Object.keys(graph).join(', ')); + +// --------------------------------------------------------------------------- +// Type inference +// --------------------------------------------------------------------------- + +// Types flow from the schema into your row types: +const _typeCheck: UserRow = {} as UserRow; +void _typeCheck; +void graph; +void AUTHORED; +void FOLLOWS; + +console.log('\nSchema definition example complete (no database required).'); diff --git a/examples/schema-definition/src/schema.ts b/examples/schema-definition/src/schema.ts new file mode 100644 index 0000000..2f90a79 --- /dev/null +++ b/examples/schema-definition/src/schema.ts @@ -0,0 +1,80 @@ +// schema.ts - Schema DSL example +// Nodes: User, Post | Relations: AUTHORED, FOLLOWS +import { + boolean, + date, + defineRel, + json, + node, + number, + relation, + schema as sch, + string, + uuid, +} from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('bio', string({ nullable: true, default: '' })) + .add('settings', json({ nullable: true })) + .add('avatarId', uuid({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .add('updatedAt', date({ nullable: true })) + .add('posts', relation('POSTED', 'OUT', 'Post', { multiple: true })) + .add('following', relation('FOLLOWS', 'OUT', 'User', { multiple: true })) + .add('followers', relation('FOLLOWS', 'IN', 'User', { multiple: true })) + .index(['email'], true) + .index(['createdAt']) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('content', string({ nullable: true })) + .add('published', boolean({ default: false })) + .add('tags', string({ array: true })) + .add('createdAt', date({ default: () => new Date() })) + .add('viewCount', number({ default: 0 })) + .add('author', relation('POSTED', 'IN', 'User')) + .add('likedBy', relation('LIKES', 'IN', 'User', { multiple: true })) + .index(['title']) + .index(['published']) + .build(); + +// Standalone relation entity with its own properties (used by the DSL example) +export const AUTHORED = defineRel('AUTHORED', 'OUT', 'Post', { + properties: { + createdAt: date({ default: () => new Date() }), + weight: number({ default: 1 }), + }, +}); + +export const FOLLOWS = defineRel('FOLLOWS', 'OUT', 'User', { + properties: { + since: date(), + }, +}); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + bio: string; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + content: string | null; + published: boolean; + tags: string[]; + viewCount: number; + createdAt: Date; +}; diff --git a/examples/schema-definition/tsconfig.json b/examples/schema-definition/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/schema-definition/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/schema-definition/vitest.config.ts b/examples/schema-definition/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/schema-definition/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/seeding/.env.example b/examples/seeding/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/seeding/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/seeding/graph.config.ts b/examples/seeding/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/seeding/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/seeding/package.json b/examples/seeding/package.json new file mode 100644 index 0000000..e53f6fa --- /dev/null +++ b/examples/seeding/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-seeding", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "SeedManager, factories, bulk insert (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/seeding/src/index.ts b/examples/seeding/src/index.ts new file mode 100644 index 0000000..330753c --- /dev/null +++ b/examples/seeding/src/index.ts @@ -0,0 +1,75 @@ +// index.ts - SeedManager, factories, bulk insert +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { createSeedManager } from '@graph-kit/sdk/seed'; +import { graph, type PostRow, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'seed-' DETACH DELETE n"); + + // Factories produce fixture data with optional overrides and an index. + const userFactory = (overrides?: Partial, index = 0): UserRow => ({ + id: `seed-user-${index}`, + name: overrides?.name ?? `User ${index}`, + email: overrides?.email ?? `user${index}@example.com`, + age: overrides?.age ?? 20 + index, + createdAt: new Date(), + }); + + const postFactory = (overrides?: Partial, index = 0): PostRow => ({ + id: `seed-post-${index}`, + title: overrides?.title ?? `Post ${index}`, + published: overrides?.published ?? index % 2 === 0, + createdAt: new Date(), + }); + + console.log('--- SeedManager with factories ---'); + const seedManager = createSeedManager({ driver, schema: graph }); + + seedManager.registerFactory('User', userFactory); + seedManager.registerFactory('Post', postFactory); + + // Clear and seed 5 users and 3 posts via factories. + const results = await seedManager.seedWithFactories({ + User: 5, + Post: 3, + }); + console.log('seed results:', results.map((r) => `${r.label}: ${r.created} created`).join(', ')); + console.log('total users:', await client.count('User')); + console.log('total posts:', await client.count('Post')); + + console.log('\n--- Bulk insert ---'); + const users = [1, 2, 3, 4, 5].map((i) => userFactory(undefined, i)); + const posts = [1, 2, 3].map((i) => postFactory(undefined, i)); + for (const u of users) { + await client.create('User', { data: u }); + } + for (const p of posts) { + await client.create('Post', { data: p }); + } + console.log('bulk inserted', users.length, 'users and', posts.length, 'posts'); + console.log('total users:', await client.count('User')); + console.log('total posts:', await client.count('Post')); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/seeding/src/schema.ts b/examples/seeding/src/schema.ts new file mode 100644 index 0000000..37cb6b4 --- /dev/null +++ b/examples/seeding/src/schema.ts @@ -0,0 +1,35 @@ +// schema.ts - Seeding example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('published', { type: 'boolean', default: false }) + .add('createdAt', date({ default: () => new Date() })) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + published: boolean; + createdAt: Date; +}; diff --git a/examples/seeding/tsconfig.json b/examples/seeding/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/seeding/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/seeding/vitest.config.ts b/examples/seeding/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/seeding/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/selective-fields/.env.example b/examples/selective-fields/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/selective-fields/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/selective-fields/graph.config.ts b/examples/selective-fields/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/selective-fields/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/selective-fields/package.json b/examples/selective-fields/package.json new file mode 100644 index 0000000..7192834 --- /dev/null +++ b/examples/selective-fields/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-selective-fields", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "select: { field: true } projection (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/selective-fields/src/index.ts b/examples/selective-fields/src/index.ts new file mode 100644 index 0000000..4287a51 --- /dev/null +++ b/examples/selective-fields/src/index.ts @@ -0,0 +1,62 @@ +// index.ts - select: { field: true } projection +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'sel-' DETACH DELETE n"); + + await client.create('User', { + data: { + id: 'sel-alice', + name: 'Alice', + email: 'alice@example.com', + age: 28, + bio: 'Engineer', + }, + }); + await client.create('User', { + data: { id: 'sel-bob', name: 'Bob', email: 'bob@example.com', age: 32, bio: 'Designer' }, + }); + await client.create('User', { + data: { id: 'sel-carol', name: 'Carol', email: 'carol@example.com', age: 25, bio: 'PM' }, + }); + + console.log('--- select only name and email ---'); + const selected = await client.findMany('User', { + select: { name: true, email: true }, + limit: 3, + }); + for (const u of selected) { + console.log(` ${u.name} <${u.email}> age=${u.age} bio=${u.bio}`); + } + + console.log('\n--- select a single field ---'); + const names = await client.findMany('User', { + select: { name: true }, + orderBy: { name: 'asc' }, + }); + console.log('names:', names.map((u) => u.name).join(', ')); + } finally { + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/selective-fields/src/schema.ts b/examples/selective-fields/src/schema.ts new file mode 100644 index 0000000..caee319 --- /dev/null +++ b/examples/selective-fields/src/schema.ts @@ -0,0 +1,23 @@ +// schema.ts - Selective fields example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('bio', string({ nullable: true, default: '' })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + bio: string; + createdAt: Date; +}; diff --git a/examples/selective-fields/tsconfig.json b/examples/selective-fields/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/selective-fields/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/selective-fields/vitest.config.ts b/examples/selective-fields/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/selective-fields/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/social-graph/graph.config.ts b/examples/social-graph/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/social-graph/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/social-graph/migrations/20240115143000_initial_schema.ts b/examples/social-graph/migrations/20240115143000_initial_schema.ts index 026bee1..66675ce 100644 --- a/examples/social-graph/migrations/20240115143000_initial_schema.ts +++ b/examples/social-graph/migrations/20240115143000_initial_schema.ts @@ -1,8 +1,8 @@ // 20240115143000_initial_schema.ts // Initial schema migration - creates constraints and indexes -import type { Migration } from '@graph-om/sdk/migration'; -import type { QueryCompiler } from '@graph-om/sdk/query'; +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; export const migration: Migration = { version: '20240115143000', diff --git a/examples/social-graph/migrations/20240116100000_add_user_bio.ts b/examples/social-graph/migrations/20240116100000_add_user_bio.ts index 803eec5..d792cdf 100644 --- a/examples/social-graph/migrations/20240116100000_add_user_bio.ts +++ b/examples/social-graph/migrations/20240116100000_add_user_bio.ts @@ -1,8 +1,8 @@ // 20240116100000_add_user_bio.ts // Add bio field to User nodes -import type { Migration } from '@graph-om/sdk/migration'; -import type { QueryCompiler } from '@graph-om/sdk/query'; +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; export const migration: Migration = { version: '20240116100000', diff --git a/examples/social-graph/migrations/20240117120000_add_post_viewcount_tags.ts b/examples/social-graph/migrations/20240117120000_add_post_viewcount_tags.ts index c32b69e..7d1f1f3 100644 --- a/examples/social-graph/migrations/20240117120000_add_post_viewcount_tags.ts +++ b/examples/social-graph/migrations/20240117120000_add_post_viewcount_tags.ts @@ -1,8 +1,8 @@ // 20240117120000_add_post_viewcount_tags.ts // Add viewCount and tags fields to Post nodes -import type { Migration } from '@graph-om/sdk/migration'; -import type { QueryCompiler } from '@graph-om/sdk/query'; +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; export const migration: Migration = { version: '20240117120000', diff --git a/examples/social-graph/migrations/20240118150000_add_user_profile_image.ts b/examples/social-graph/migrations/20240118150000_add_user_profile_image.ts index 1acb261..7a2f8ee 100644 --- a/examples/social-graph/migrations/20240118150000_add_user_profile_image.ts +++ b/examples/social-graph/migrations/20240118150000_add_user_profile_image.ts @@ -1,8 +1,8 @@ // 20240118150000_add_user_profile_image.ts // Add profileImageUrl field to User nodes -import type { Migration } from '@graph-om/sdk/migration'; -import type { QueryCompiler } from '@graph-om/sdk/query'; +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; export const migration: Migration = { version: '20240118150000', diff --git a/examples/social-graph/migrations/20240119110000_add_bookmark_relation.ts b/examples/social-graph/migrations/20240119110000_add_bookmark_relation.ts index 3004edb..56f6dd1 100644 --- a/examples/social-graph/migrations/20240119110000_add_bookmark_relation.ts +++ b/examples/social-graph/migrations/20240119110000_add_bookmark_relation.ts @@ -1,8 +1,8 @@ // 20240119110000_add_bookmark_relation.ts // Add BOOKMARKED relationship type -import type { Migration } from '@graph-om/sdk/migration'; -import type { QueryCompiler } from '@graph-om/sdk/query'; +import type { Migration } from '@graph-kit/sdk/migration'; +import type { QueryCompiler } from '@graph-kit/sdk/query'; export const migration: Migration = { version: '20240119110000', diff --git a/examples/social-graph/package.json b/examples/social-graph/package.json index 921b59e..ca02814 100644 --- a/examples/social-graph/package.json +++ b/examples/social-graph/package.json @@ -18,20 +18,20 @@ "start:errors-constraints": "tsx src/errors-constraints.ts", "start:errors-public": "tsx src/errors-public.ts", "seed": "tsx src/seed.ts", - "generate": "graph-om generate", + "generate": "graph-kit generate", "typecheck": "tsc --noEmit", "test": "vitest run --passWithNoTests", "test:ui": "vitest --ui", "clean": "rm -rf .turbo dist" }, "dependencies": { - "@graph-om/sdk": "workspace:*", - "@graph-om/zod": "workspace:*", + "@graph-kit/sdk": "workspace:*", + "@graph-kit/zod": "workspace:*", "zod": "^4.6.7" }, "devDependencies": { "@apollo/server": "^5.5.1", - "@graph-om/cli": "workspace:*", + "@graph-kit/cli": "workspace:*", "@types/node": "^20.0.0", "tsx": "^4.23.15", "typescript": "^5.9.3", diff --git a/examples/social-graph/src/aggregations.ts b/examples/social-graph/src/aggregations.ts index 829dc45..fb15ed5 100644 --- a/examples/social-graph/src/aggregations.ts +++ b/examples/social-graph/src/aggregations.ts @@ -1,8 +1,8 @@ // aggregations.ts - count / sum / avg / min / max and grouped stats // Run: pnpm start:aggregations -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/comprehensive.ts b/examples/social-graph/src/comprehensive.ts index 08650ac..f6542d5 100644 --- a/examples/social-graph/src/comprehensive.ts +++ b/examples/social-graph/src/comprehensive.ts @@ -1,8 +1,8 @@ -// comprehensive.ts - Comprehensive Graph-OM Examples -// Demonstrates all major features of the Graph-OM library +// comprehensive.ts - Comprehensive Graph-Kit Examples +// Demonstrates all major features of the Graph-Kit library -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const URI = process.env.NEO4J_URI || 'bolt://localhost:7687'; @@ -35,7 +35,7 @@ async function main() { "MATCH (n) WHERE n.id STARTS WITH 'user-' OR n.id STARTS WITH 'post-' DETACH DELETE n", ); - console.log('=== COMPREHENSIVE GRAPH-OM EXAMPLES ===\n'); + console.log('=== COMPREHENSIVE GRAPH-KIT EXAMPLES ===\n'); // ============================================================ // BASIC CRUD OPERATIONS diff --git a/examples/social-graph/src/errors-constraints.ts b/examples/social-graph/src/errors-constraints.ts index 90611b5..66bd92e 100644 --- a/examples/social-graph/src/errors-constraints.ts +++ b/examples/social-graph/src/errors-constraints.ts @@ -2,8 +2,8 @@ // Run: pnpm start:errors-constraints // Needs a running Neo4j (docker compose up -d from the repo root). -import { GraphClient, hasCode } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient, hasCode } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/errors-handling.ts b/examples/social-graph/src/errors-handling.ts index 696ffe9..784204b 100644 --- a/examples/social-graph/src/errors-handling.ts +++ b/examples/social-graph/src/errors-handling.ts @@ -2,8 +2,8 @@ // Run: pnpm start:errors-handling // Parts 1 and 2 need no database: the client rejects unknown labels before it sends any query. -import { GraphClient, getRootCause, hasCode, isFrontalError } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient, getRootCause, hasCode, isFrontalError } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/errors-public.ts b/examples/social-graph/src/errors-public.ts index 8fbf971..fb0af46 100644 --- a/examples/social-graph/src/errors-public.ts +++ b/examples/social-graph/src/errors-public.ts @@ -2,9 +2,9 @@ // Run: pnpm start:errors-public // No database needed: this builds errors by hand, the way the SDK does internally. -import { GraphError } from '@graph-om/sdk'; -import { errorResponse, formatError, toPublic } from '@graph-om/sdk/errors'; -import { toGraphQLError } from '@graph-om/sdk/graphql'; +import { GraphError } from '@graph-kit/sdk'; +import { errorResponse, formatError, toPublic } from '@graph-kit/sdk/errors'; +import { toGraphQLError } from '@graph-kit/sdk/graphql'; // An internal failure, with details that must never reach a client const internal = new GraphError('Failed to update User: record not found', { @@ -28,7 +28,7 @@ console.log( JSON.stringify((graphQLError as Error & { extensions: unknown }).extensions), ); -// 3. Errors that are not graph-om errors get a generic response, with no internal text +// 3. Errors that are not graph-kit errors get a generic response, with no internal text const unexpected = new Error('socket hang up at 10.0.0.4:7687'); const generic = errorResponse(toPublic(unexpected)); console.log('3. unexpected error -> HTTP', generic.status, generic.body); diff --git a/examples/social-graph/src/errors-retry.ts b/examples/social-graph/src/errors-retry.ts index 1d839e9..4e814d8 100644 --- a/examples/social-graph/src/errors-retry.ts +++ b/examples/social-graph/src/errors-retry.ts @@ -2,8 +2,8 @@ // Run: pnpm start:errors-retry // Uses a port nothing listens on, so it runs without a database. -import { hasCode, isRetryable } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { hasCode, isRetryable } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; const MAX_ATTEMPTS = 3; diff --git a/examples/social-graph/src/graphql.ts b/examples/social-graph/src/graphql.ts index edbb31d..859171b 100644 --- a/examples/social-graph/src/graphql.ts +++ b/examples/social-graph/src/graphql.ts @@ -1,12 +1,12 @@ // graphql.ts - Generate GraphQL SDL and resolvers from the schema // Run: pnpm start:graphql // -// @graph-om/sdk generates the SDL and the resolver map. It does not start a server: plug the +// @graph-kit/sdk generates the SDL and the resolver map. It does not start a server: plug the // resolvers into your GraphQL server of choice (Apollo, Yoga, graphql-js). -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; -import { generateGraphQLSchema, generateResolvers } from '@graph-om/sdk/graphql'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { generateGraphQLSchema, generateResolvers } from '@graph-kit/sdk/graphql'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/includes.ts b/examples/social-graph/src/includes.ts index 890e1ff..da9dda8 100644 --- a/examples/social-graph/src/includes.ts +++ b/examples/social-graph/src/includes.ts @@ -1,8 +1,8 @@ // includes.ts - Loading relations with `include` // Run: pnpm start:includes -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/index.ts b/examples/social-graph/src/index.ts index 4d6367d..e440a6e 100644 --- a/examples/social-graph/src/index.ts +++ b/examples/social-graph/src/index.ts @@ -1,8 +1,8 @@ -// index.ts - Basic CRUD with the Graph-OM client +// index.ts - Basic CRUD with the Graph-Kit client // Run: pnpm start -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/migrations.ts b/examples/social-graph/src/migrations.ts index ea24798..d1a0da6 100644 --- a/examples/social-graph/src/migrations.ts +++ b/examples/social-graph/src/migrations.ts @@ -1,11 +1,11 @@ // migrations.ts - Applying, checking, and rolling back migrations // Run: pnpm start:migrations // -// The migration modules are imported explicitly. `loadMigrations()` in @graph-om/sdk does not +// The migration modules are imported explicitly. `loadMigrations()` in @graph-kit/sdk does not // import files yet, so the list is built here from the files in ../migrations. -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; -import { createMigrationRunner, type Migration } from '@graph-om/sdk/migration'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { createMigrationRunner, type Migration } from '@graph-kit/sdk/migration'; import { migration as initialSchema } from '../migrations/20240115143000_initial_schema.js'; import { migration as addUserBio } from '../migrations/20240116100000_add_user_bio.js'; import { migration as addPostViewcountTags } from '../migrations/20240117120000_add_post_viewcount_tags.js'; diff --git a/examples/social-graph/src/pagination.ts b/examples/social-graph/src/pagination.ts index ff4637b..566ac9a 100644 --- a/examples/social-graph/src/pagination.ts +++ b/examples/social-graph/src/pagination.ts @@ -1,8 +1,8 @@ // pagination.ts - Offset, cursor, and paged-include examples // Run: pnpm start:pagination -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/src/schema.ts b/examples/social-graph/src/schema.ts index 40510f6..d8b86e6 100644 --- a/examples/social-graph/src/schema.ts +++ b/examples/social-graph/src/schema.ts @@ -1,5 +1,5 @@ // schema.ts - Social Graph Schema -import { date, node, number, relation, schema as sch, string } from '@graph-om/sdk'; +import { date, node, number, relation, schema as sch, string } from '@graph-kit/sdk'; export const User = node('User') .add('id', string({ primary: true })) diff --git a/examples/social-graph/src/seed.ts b/examples/social-graph/src/seed.ts index 0f38f72..ef029c8 100644 --- a/examples/social-graph/src/seed.ts +++ b/examples/social-graph/src/seed.ts @@ -1,7 +1,7 @@ // seed.ts - Seed the social graph database -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const URI = process.env.NEO4J_URI || 'bolt://localhost:7687'; diff --git a/examples/social-graph/src/testing.ts b/examples/social-graph/src/testing.ts index 27e5d4a..34beada 100644 --- a/examples/social-graph/src/testing.ts +++ b/examples/social-graph/src/testing.ts @@ -6,8 +6,8 @@ // against a real database (see includes.ts and pagination.ts). import assert from 'node:assert/strict'; -import { GraphClient } from '@graph-om/sdk'; -import { createMockDriver, createTestFixtures, generateRandomEmail } from '@graph-om/sdk/testing'; +import { GraphClient } from '@graph-kit/sdk'; +import { createMockDriver, createTestFixtures, generateRandomEmail } from '@graph-kit/sdk/testing'; import { graph } from './schema.js'; type UserRow = { id: string; name: string; email: string; age: number | null }; diff --git a/examples/social-graph/src/transactions.ts b/examples/social-graph/src/transactions.ts index 32a4abc..ab36b4b 100644 --- a/examples/social-graph/src/transactions.ts +++ b/examples/social-graph/src/transactions.ts @@ -1,8 +1,8 @@ // transactions.ts - Atomic multi-step writes with client.transaction() // Run: pnpm start:transactions -import { GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; const driver = createNeo4jDriver({ diff --git a/examples/social-graph/tsconfig.json b/examples/social-graph/tsconfig.json index 26d2f93..212a916 100644 --- a/examples/social-graph/tsconfig.json +++ b/examples/social-graph/tsconfig.json @@ -8,5 +8,5 @@ "skipLibCheck": true, "noEmit": true }, - "include": ["src", "migrations", "graph-om.config.ts"] + "include": ["src", "migrations", "graph.config.ts"] } diff --git a/examples/social-graph/vitest.config.ts b/examples/social-graph/vitest.config.ts index f6638fc..6981819 100644 --- a/examples/social-graph/vitest.config.ts +++ b/examples/social-graph/vitest.config.ts @@ -13,18 +13,18 @@ export default defineConfig({ }, resolve: { alias: { - '@graph-om/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), - '@graph-om/sdk/driver/neo4j': path.resolve( + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + '@graph-kit/sdk/driver/neo4j': path.resolve( __dirname, '../../packages/sdk/src/driver/neo4j.ts', ), - '@graph-om/zod': path.resolve(__dirname, '../../packages/zod/src/index.ts'), - '@graph-om/testing': path.resolve(__dirname, '../../packages/sdk/src/testing/index.ts'), - '@graph-om/sdk/migration': path.resolve( + '@graph-kit/zod': path.resolve(__dirname, '../../packages/zod/src/index.ts'), + '@graph-kit/testing': path.resolve(__dirname, '../../packages/sdk/src/testing/index.ts'), + '@graph-kit/sdk/migration': path.resolve( __dirname, '../../packages/sdk/src/migration/index.ts', ), - '@graph-om/sdk/graphql': path.resolve(__dirname, '../../packages/sdk/src/graphql/index.ts'), + '@graph-kit/sdk/graphql': path.resolve(__dirname, '../../packages/sdk/src/graphql/index.ts'), }, }, }); diff --git a/examples/transactions/.env.example b/examples/transactions/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/transactions/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/transactions/graph.config.ts b/examples/transactions/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/transactions/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/transactions/package.json b/examples/transactions/package.json new file mode 100644 index 0000000..18edb7c --- /dev/null +++ b/examples/transactions/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-transactions", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Atomic multi-step writes, rollback (requires Neo4j)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/transactions/src/index.ts b/examples/transactions/src/index.ts new file mode 100644 index 0000000..1be7c18 --- /dev/null +++ b/examples/transactions/src/index.ts @@ -0,0 +1,78 @@ +// index.ts - Atomic multi-step writes, rollback +// Run: pnpm start +// Requires Neo4j + +import { GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { graph, type PostRow, type UserRow } from './schema.js'; + +const driver = createNeo4jDriver({ + type: 'neo4j', + uri: process.env.NEO4J_URI ?? 'bolt://localhost:7687', + username: process.env.NEO4J_USER ?? 'neo4j', + password: process.env.NEO4J_PASSWORD ?? 'password', +}); + +async function main() { + await driver.connect(); + const client = new GraphClient(driver, graph); + + try { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'tx-' DETACH DELETE n"); + + // 1. Everything inside the callback commits together + console.log('--- committing transaction ---'); + await client.transaction(async (tx) => { + await tx.create('User', { + data: { id: 'tx-author', name: 'Author', email: 'author@tx.example', age: 40 }, + }); + await tx.create('Post', { + data: { id: 'tx-post-1', title: 'Atomic writes', published: true }, + }); + await tx.raw( + `MATCH (u:User {id: $userId}), (p:Post {id: $postId}) + CREATE (u)-[:POSTED]->(p)`, + { userId: 'tx-author', postId: 'tx-post-1' }, + ); + }); + const committed = await client.findUnique('Post', { + where: { id: 'tx-post-1' }, + include: { author: true }, + }); + console.log('committed post author:', committed?.author?.name); + + // 2. If the callback throws, every write is rolled back + console.log('\n--- rolling back a transaction ---'); + await client + .transaction(async (tx) => { + await tx.create('Post', { + data: { id: 'tx-post-2', title: 'Never committed', published: false }, + }); + throw new Error('payment provider timed out'); + }) + .catch((error: Error) => console.log('rolled back because:', error.message)); + const rolledBack = await client.findUnique('Post', { where: { id: 'tx-post-2' } }); + console.log('tx-post-2 exists after rollback:', rolledBack !== null); + + // 3. Reads inside a transaction see the transaction's own uncommitted writes + console.log('\n--- read uncommitted writes inside a transaction ---'); + const seen = await client.transaction(async (tx) => { + await tx.create('Post', { + data: { id: 'tx-post-3', title: 'Visible inside', published: true }, + }); + return tx.findMany('Post', { where: { id: { eq: 'tx-post-3' } } }); + }); + console.log( + 'visible inside transaction:', + seen.map((p) => p.title), + ); + } finally { + await client.raw("MATCH (n) WHERE n.id STARTS WITH 'tx-' DETACH DELETE n"); + await driver.disconnect(); + } +} + +main().catch((error: unknown) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/transactions/src/schema.ts b/examples/transactions/src/schema.ts new file mode 100644 index 0000000..6664f02 --- /dev/null +++ b/examples/transactions/src/schema.ts @@ -0,0 +1,37 @@ +// schema.ts - Transactions example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const Post = node('Post') + .add('id', string({ primary: true })) + .add('title', string()) + .add('content', string({ nullable: true })) + .add('published', { type: 'boolean', default: false }) + .add('createdAt', date({ default: () => new Date() })) + .build(); + +export const graph = sch().add('User', User).add('Post', Post).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; + +export type PostRow = { + id: string; + title: string; + content: string | null; + published: boolean; + createdAt: Date; +}; diff --git a/examples/transactions/tsconfig.json b/examples/transactions/tsconfig.json new file mode 100644 index 0000000..fe047e5 --- /dev/null +++ b/examples/transactions/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/transactions/vitest.config.ts b/examples/transactions/vitest.config.ts new file mode 100644 index 0000000..5fc975c --- /dev/null +++ b/examples/transactions/vitest.config.ts @@ -0,0 +1,15 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + }, + }, +}); diff --git a/examples/zod-validation/.env.example b/examples/zod-validation/.env.example new file mode 100644 index 0000000..f739a87 --- /dev/null +++ b/examples/zod-validation/.env.example @@ -0,0 +1,3 @@ +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=password diff --git a/examples/zod-validation/graph.config.ts b/examples/zod-validation/graph.config.ts new file mode 100644 index 0000000..480babb --- /dev/null +++ b/examples/zod-validation/graph.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from '@graph-kit/sdk'; + +export default defineConfig({ + schema: './src/schema.ts', + output: { + directory: './src/__generated__', + zod: true, + }, + driver: { + type: 'neo4j', + uri: process.env.NEO4J_URI || 'bolt://localhost:7687', + username: process.env.NEO4J_USER || 'neo4j', + password: process.env.NEO4J_PASSWORD || 'password', + }, + debug: false, +}); diff --git a/examples/zod-validation/package.json b/examples/zod-validation/package.json new file mode 100644 index 0000000..be27940 --- /dev/null +++ b/examples/zod-validation/package.json @@ -0,0 +1,27 @@ +{ + "name": "example-zod-validation", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "toCreateSchema, validateCreate, hooks (no database required)", + "scripts": { + "start": "tsx src/index.ts", + "generate": "graph-kit generate", + "typecheck": "tsc --noEmit", + "test": "vitest run --passWithNoTests", + "clean": "rm -rf .turbo dist" + }, + "dependencies": { + "@graph-kit/sdk": "workspace:*", + "@graph-kit/zod": "workspace:*", + "zod": "^4.6.7" + }, + "devDependencies": { + "@graph-kit/cli": "workspace:*", + "@types/node": "^20.0.0", + "tsx": "^4.23.15", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.12" + } +} diff --git a/examples/zod-validation/src/index.ts b/examples/zod-validation/src/index.ts new file mode 100644 index 0000000..bae0ea6 --- /dev/null +++ b/examples/zod-validation/src/index.ts @@ -0,0 +1,78 @@ +// index.ts - toCreateSchema, validateCreate, hooks +// Run: pnpm start +// Does NOT require a database. + +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; +import { toCreateSchema, toUpdateSchema, validateCreate, validateUpdate } from '@graph-kit/zod'; +import type { z } from 'zod'; + +// --------------------------------------------------------------------------- +// Define a node config +// --------------------------------------------------------------------------- + +const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .build(); + +const graph = sch().add('User', User).build(); + +// --------------------------------------------------------------------------- +// Generate Zod schemas from the node config +// --------------------------------------------------------------------------- + +const createSchema = toCreateSchema(User); +const updateSchema = toUpdateSchema(User); + +// Custom Zod refinement: email must contain "@" +const createSchemaWithRefine = createSchema.refine( + (data) => String(data.email ?? '').includes('@'), + { + message: 'Email must contain "@"', + path: ['email'], + }, +); + +// --------------------------------------------------------------------------- +// validateCreate / validateUpdate +// --------------------------------------------------------------------------- + +function show(label: string, result: { success: boolean; data?: unknown; error?: unknown }) { + if (result.success) { + console.log(` ${label}: OK ->`, JSON.stringify(result.data)); + } else { + console.log( + ` ${label}: FAILED ->`, + (result.error as z.ZodError).issues.map((i) => i.message).join(', '), + ); + } +} + +console.log('--- validateCreate ---'); +show( + 'valid user', + validateCreate(User, { id: 'u-1', name: 'Alice', email: 'alice@example.com', age: 28 }), +); +show('missing required name', validateCreate(User, { id: 'u-2', email: 'bob@example.com' })); +const badEmail = createSchemaWithRefine.safeParse({ + id: 'u-3', + name: 'Bob', + email: 'bob-example.com', + age: 30, +}); +show('bad email (no @)', badEmail); + +console.log('\n--- validateUpdate ---'); +show('valid update (partial)', validateUpdate(User, { name: 'Alice Updated' })); +show('update primary key not allowed (id optional)', validateUpdate(User, { id: 'u-1' })); + +console.log('\n--- toZodSchema full shape ---'); +const fullSchema = createSchema; +console.log('create schema keys:', Object.keys(fullSchema.shape)); + +void graph; + +console.log('\nZod validation example complete (no database required).'); diff --git a/examples/zod-validation/src/schema.ts b/examples/zod-validation/src/schema.ts new file mode 100644 index 0000000..0f4ec5f --- /dev/null +++ b/examples/zod-validation/src/schema.ts @@ -0,0 +1,21 @@ +// schema.ts - Zod validation example schema +import { date, node, number, schema as sch, string } from '@graph-kit/sdk'; + +export const User = node('User') + .add('id', string({ primary: true })) + .add('name', string()) + .add('email', string({ unique: true })) + .add('age', number({ nullable: true })) + .add('createdAt', date({ default: () => new Date() })) + .index(['email'], true) + .build(); + +export const graph = sch().add('User', User).build(); + +export type UserRow = { + id: string; + name: string; + email: string; + age: number | null; + createdAt: Date; +}; diff --git a/examples/zod-validation/tsconfig.json b/examples/zod-validation/tsconfig.json new file mode 100644 index 0000000..342ce43 --- /dev/null +++ b/examples/zod-validation/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + "baseUrl": ".", + "paths": { + "@graph-kit/zod": ["../../packages/zod/src/index.ts"] + } + }, + "include": ["src", "graph.config.ts"] +} diff --git a/examples/zod-validation/vitest.config.ts b/examples/zod-validation/vitest.config.ts new file mode 100644 index 0000000..5d92039 --- /dev/null +++ b/examples/zod-validation/vitest.config.ts @@ -0,0 +1,16 @@ +import path from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts'], + }, + resolve: { + alias: { + '@graph-kit/sdk': path.resolve(__dirname, '../../packages/sdk/src/index.ts'), + '@graph-kit/zod': path.resolve(__dirname, '../../packages/zod/src/index.ts'), + }, + }, +}); diff --git a/package.json b/package.json index 1a0fb6a..4220718 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { - "name": "graph-om", + "name": "graph-kit", "version": "1.0.0", "private": true, - "description": "Graph-OM - Prisma-like DX for graph databases (monorepo)", + "description": "Graph-Kit - Prisma-like DX for graph databases (monorepo)", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git" + "url": "https://github.com/frontal-labs/graph-kit.git" }, "scripts": { "prepare": "husky", @@ -19,8 +19,8 @@ "test:coverage": "turbo run test:coverage", "test:root": "vitest run", "test:root:ci": "vitest run --reporter=verbose", - "benchmark": "pnpm --filter @graph-om/sdk run benchmark", - "benchmark:ci": "pnpm --filter @graph-om/sdk run benchmark:ci", + "benchmark": "pnpm --filter @graph-kit/sdk run benchmark", + "benchmark:ci": "pnpm --filter @graph-kit/sdk run benchmark:ci", "lint": "ultracite check", "typecheck": "turbo run typecheck", "format": "ultracite fix", @@ -65,6 +65,6 @@ } }, "bin": { - "graph-om": "./bin/index.js" + "graph-kit": "./bin/index.js" } } diff --git a/packages/cli/README.md b/packages/cli/README.md index 388004b..9c45510 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,19 +1,19 @@ -# @graph-om/cli +# @graph-kit/cli -CLI for Graph-OM. +CLI for Graph-Kit. ```bash -npx graph-om init [directory] # scaffold a new project -npx graph-om generate # generate types/client (and zod) from schema -npx graph-om generate --watch # regenerate on schema changes +npx graph-kit init [directory] # scaffold a new project +npx graph-kit generate # generate types/client (and zod) from schema +npx graph-kit generate --watch # regenerate on schema changes ``` -Reads `graph-om.config.ts` (or `graph-om.config.json`) for the schema path, output directory, zod flag, and excluded labels. +Reads `graph-kit.config.ts` (or `graph-kit.config.json`) for the schema path, output directory, zod flag, and excluded labels. Generated files land in `src/__generated__` by default: - `types.ts` — node interfaces, `Where`, `CreateInput`, `UpdateInput` types -- `client.ts` — `createClient()` factory wiring `@graph-om/sdk/driver/neo4j` to `GraphClient` +- `client.ts` — `createClient()` factory wiring `@graph-kit/sdk/driver/neo4j` to `GraphClient` - `zod.ts` — Zod schemas (when `output.zod: true`) ## License diff --git a/packages/cli/package.json b/packages/cli/package.json index 472c002..b4d1e01 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,23 +1,23 @@ { - "name": "@graph-om/cli", + "name": "@graph-kit/cli", "version": "0.0.1", - "description": "CLI for Graph-OM - init and generate", + "description": "CLI for Graph-Kit - init and generate", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git", + "url": "https://github.com/frontal-labs/graph-kit.git", "directory": "packages/cli" }, - "homepage": "https://github.com/frontal-labs/graph-om/tree/master/cli#readme", + "homepage": "https://github.com/frontal-labs/graph-kit/tree/master/cli#readme", "bugs": { - "url": "https://github.com/frontal-labs/graph-om/issues" + "url": "https://github.com/frontal-labs/graph-kit/issues" }, "keywords": [ "ogm", "cli", "codegen", "neo4j", - "graph-om" + "graph-kit" ], "sideEffects": false, "files": [ @@ -28,7 +28,7 @@ "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "bin": { - "graph-om": "./dist/index.mjs" + "graph-kit": "./dist/index.mjs" }, "exports": { ".": { @@ -48,7 +48,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@graph-om/sdk": "workspace:*", + "@graph-kit/sdk": "workspace:*", "commander": "^15.0.0" }, "devDependencies": { diff --git a/packages/cli/src/commands/diff.ts b/packages/cli/src/commands/diff.ts index a5d74bb..471377b 100644 --- a/packages/cli/src/commands/diff.ts +++ b/packages/cli/src/commands/diff.ts @@ -1,4 +1,4 @@ -// @graph-om/cli/src/commands/diff.ts +// @graph-kit/cli/src/commands/diff.ts import { execFileSync } from 'node:child_process'; import fs from 'node:fs'; @@ -12,17 +12,17 @@ import { type PropertyConfig, type PropertyType, type RelationConfig, -} from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; -import { raiseGraphError } from '@graph-om/sdk/errors'; +} from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { raiseGraphError } from '@graph-kit/sdk/errors'; import { diffSchemas, type NodeDiff, type PropertyDiff, type RelationDiff, type SchemaDiff, -} from '@graph-om/sdk/migration'; -import { parseSchemaFile } from '@graph-om/sdk/schema'; +} from '@graph-kit/sdk/migration'; +import { parseSchemaFile } from '@graph-kit/sdk/schema'; import { Command } from 'commander'; import { loadProjectConfig } from './generate.js'; diff --git a/packages/cli/src/commands/generate.ts b/packages/cli/src/commands/generate.ts index bc1ca39..2805eab 100644 --- a/packages/cli/src/commands/generate.ts +++ b/packages/cli/src/commands/generate.ts @@ -1,8 +1,8 @@ -// @graph-om/cli/src/commands/generate.ts +// @graph-kit/cli/src/commands/generate.ts import fs from 'node:fs'; import path from 'node:path'; -import { type ParsedNode, parseSchemaFile } from '@graph-om/sdk'; -import { raiseGraphError } from '@graph-om/sdk/errors'; +import { type ParsedNode, parseSchemaFile } from '@graph-kit/sdk'; +import { raiseGraphError } from '@graph-kit/sdk/errors'; interface GenerateOptions { watch?: boolean; @@ -165,9 +165,9 @@ function generateZodSchema(node: NodeDef): string { } export function generateTypesContent(nodes: NodeDef[]): string { - return `// Auto-generated by Graph-OM CLI + return `// Auto-generated by Graph-Kit CLI // Type definitions for your graph schema -import type { WhereOperator } from '@graph-om/sdk'; +import type { WhereOperator } from '@graph-kit/sdk'; ${nodes.map((n) => generateNodeInterface(n)).join('\n\n')} @@ -180,7 +180,7 @@ ${nodes.map((n) => generateUpdateType(n)).join('\n\n')} } export function generateZodContent(nodes: NodeDef[]): string { - return `// Auto-generated by Graph-OM CLI + return `// Auto-generated by Graph-Kit CLI // Zod schemas for your graph schema import { z } from 'zod'; @@ -203,10 +203,10 @@ export function generateClientContent(nodes: NodeDef[]): string { }) .join(',\n'); - return `// Auto-generated by Graph-OM CLI -import { GraphClient, env } from '@graph-om/sdk'; -import type { DriverAdapter, NodeConfig } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; + return `// Auto-generated by Graph-Kit CLI +import { GraphClient, env } from '@graph-kit/sdk'; +import type { DriverAdapter, NodeConfig } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import type { ${imports} } from './types.js'; export type GraphNodeMap = { @@ -252,10 +252,18 @@ export function loadProjectConfig(projectRoot: string): LoadedProjectConfig { let zod = false; let exclude: string[] = []; - const configPath = path.join(projectRoot, 'graph-om.config.ts'); - const configJsonPath = path.join(projectRoot, 'graph-om.config.json'); + // Preferred config filename first, then the legacy graph-kit.config.* names. + const configCandidates = [ + path.join(projectRoot, 'graph.config.ts'), + path.join(projectRoot, 'graph.config.json'), + path.join(projectRoot, 'graph-kit.config.ts'), + path.join(projectRoot, 'graph-kit.config.json'), + ]; + + const configJsonPath = configCandidates.find((p) => p.endsWith('.json') && fs.existsSync(p)); + const configPath = configCandidates.find((p) => p.endsWith('.ts') && fs.existsSync(p)); - if (fs.existsSync(configJsonPath)) { + if (configJsonPath) { const raw = fs.readFileSync(configJsonPath, 'utf-8'); try { const parsed = JSON.parse(raw) as { @@ -268,9 +276,9 @@ export function loadProjectConfig(projectRoot: string): LoadedProjectConfig { if (parsed.output?.zod) zod = true; if (Array.isArray(parsed.exclude)) exclude = parsed.exclude; } catch { - console.warn('⚠ Could not parse graph-om.config.json, using defaults.'); + console.warn(`⚠ Could not parse ${configJsonPath}, using defaults.`); } - } else if (fs.existsSync(configPath)) { + } else if (configPath) { const raw = fs.readFileSync(configPath, 'utf-8'); const schemaMatch = raw.match(/schema:\s*['"]([^'"]+)['"]/); const outputMatch = raw.match(/directory:\s*['"]([^'"]+)['"]/); @@ -297,7 +305,7 @@ export function runGenerate(projectRoot: string): GenerateResult { if (!fs.existsSync(schemaPath)) { raiseGraphError( `Schema file not found at ${schemaPath}. ` + - `Check the "schema" field in graph-om.config.ts or run \`graph-om init\`.`, + `Check the "schema" field in graph.config.ts or run \`graph-kit init\`.`, { code: 'invalid_config', statusCode: 400 }, ); } diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 7cf7244..3ebdd3e 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -1,4 +1,4 @@ -// @graph-om/cli/src/commands/init.ts +// @graph-kit/cli/src/commands/init.ts import fs from 'node:fs'; import path from 'node:path'; import { cliVersion } from '../version.js'; @@ -23,16 +23,16 @@ export async function initCommand(directory: string, _options: InitOptions): Pro private: true, type: 'module', scripts: { - generate: 'graph-om generate', - build: 'graph-om generate && tsc --noEmit', + generate: 'graph-kit generate', + build: 'graph-kit generate && tsc --noEmit', start: 'tsx src/index.ts', typecheck: 'tsc --noEmit', }, dependencies: { - '@graph-om/sdk': `^${cliVersion()}`, + '@graph-kit/sdk': `^${cliVersion()}`, }, devDependencies: { - '@graph-om/cli': `^${cliVersion()}`, + '@graph-kit/cli': `^${cliVersion()}`, typescript: '^5.3.0', tsx: '^4.0.0', '@types/node': '^20.0.0', @@ -61,8 +61,8 @@ export async function initCommand(directory: string, _options: InitOptions): Pro fs.mkdirSync(path.join(targetDir, 'src'), { recursive: true }); - const schemaContent = `// graph-om/schema.ts - Define your graph schema -import { node, defineRel, schema as sch, string, number, date } from '@graph-om/sdk'; + const schemaContent = `// graph-kit/schema.ts - Define your graph schema +import { node, defineRel, schema as sch, string, number, date } from '@graph-kit/sdk'; export const User = node('User') .add('id', string({ primary: true })) @@ -79,8 +79,8 @@ export const graph = sch() fs.writeFileSync(path.join(targetDir, 'src', 'schema.ts'), schemaContent); const mainContent = `// src/index.ts -import { GraphClient, env } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { GraphClient, env } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; import { graph } from './schema.js'; async function main() { @@ -108,8 +108,8 @@ main().catch((error) => { fs.writeFileSync(path.join(targetDir, 'src', 'index.ts'), mainContent); - // Generate graph-om.config.ts — the single source of truth for Graph-OM - const graphOmConfigContent = `import { defineConfig, env } from '@graph-om/sdk'; + // Generate graph.config.ts — the single source of truth for Graph-Kit + const graphOmConfigContent = `import { defineConfig, env } from '@graph-kit/sdk'; export default defineConfig({ schema: './src/schema.ts', @@ -127,7 +127,7 @@ export default defineConfig({ }); `; - fs.writeFileSync(path.join(targetDir, 'graph-om.config.ts'), graphOmConfigContent); + fs.writeFileSync(path.join(targetDir, 'graph.config.ts'), graphOmConfigContent); const envContent = `NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j @@ -135,12 +135,12 @@ NEO4J_PASSWORD=password `; fs.writeFileSync(path.join(targetDir, '.env.example'), envContent); - console.log(`\n✓ Initialized Graph-OM project in "${targetDir}"`); + console.log(`\n✓ Initialized Graph-Kit project in "${targetDir}"`); console.log('\nNext steps:'); console.log(` 1. cd ${directory}`); console.log(' 2. Install dependencies (pnpm install / npm install / yarn)'); console.log(' 3. Copy .env.example to .env and set your Neo4j connection'); console.log(' 4. Edit src/schema.ts to define your graph'); - console.log(' 5. npx graph-om generate'); + console.log(' 5. npx graph-kit generate'); console.log(' 6. npx tsx src/index.ts\n'); } diff --git a/packages/cli/src/commands/migrate.ts b/packages/cli/src/commands/migrate.ts index 27257f7..332bd0c 100644 --- a/packages/cli/src/commands/migrate.ts +++ b/packages/cli/src/commands/migrate.ts @@ -1,10 +1,10 @@ -// @graph-om/cli/src/commands/migrate.ts +// @graph-kit/cli/src/commands/migrate.ts import fs from 'node:fs'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; -import { env } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; -import { raiseGraphError } from '@graph-om/sdk/errors'; +import { env } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { raiseGraphError } from '@graph-kit/sdk/errors'; import { createMigrationRunner, createMigrationTemplate, @@ -12,7 +12,7 @@ import { type Migration, type RelationDiff, type SchemaDiff, -} from '@graph-om/sdk/migration'; +} from '@graph-kit/sdk/migration'; import { Command } from 'commander'; import { loadProjectConfig } from './generate.js'; @@ -91,7 +91,7 @@ async function runMigrateUp(migrationsDir: string): Promise { const { schemaPath } = config; // Load schema to pass to migration runner - const { parseSchemaFile } = await import('@graph-om/sdk/schema'); + const { parseSchemaFile } = await import('@graph-kit/sdk/schema'); const result = parseSchemaFile(schemaPath); const schema = result.schema; @@ -133,7 +133,7 @@ async function runMigrateDown(migrationsDir: string, steps: number): Promise { const config = loadProjectConfig(projectRoot); const { schemaPath } = config; - const { parseSchemaFile } = await import('@graph-om/sdk/schema'); + const { parseSchemaFile } = await import('@graph-kit/sdk/schema'); const result = parseSchemaFile(schemaPath); const schema = result.schema; @@ -227,7 +227,7 @@ async function runMigrateDiff(name: string, migrationsDir: string): Promise { content = `// Seed: ${name} // Relational seed with factories -import { createSeedManager, Fixtures, createUserFactory, createPostFactory } from '@graph-om/sdk/seed'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; -import { env } from '@graph-om/sdk'; -import { parseSchemaFile } from '@graph-om/sdk/schema'; +import { createSeedManager, Fixtures, createUserFactory, createPostFactory } from '@graph-kit/sdk/seed'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; +import { env } from '@graph-kit/sdk'; +import { parseSchemaFile } from '@graph-kit/sdk/schema'; const schemaPath = './src/schema.ts'; const result = parseSchemaFile(schemaPath); diff --git a/packages/cli/src/commands/studio.ts b/packages/cli/src/commands/studio.ts index 601619b..712362b 100644 --- a/packages/cli/src/commands/studio.ts +++ b/packages/cli/src/commands/studio.ts @@ -1,10 +1,10 @@ -// @graph-om/cli/src/commands/studio.ts +// @graph-kit/cli/src/commands/studio.ts import { exec } from 'node:child_process'; import fs from 'node:fs'; import path from 'node:path'; -import { parseSchemaFile } from '@graph-om/sdk/schema'; -import { generateDocumentation, generateERDiagram } from '@graph-om/sdk/visualization'; +import { parseSchemaFile } from '@graph-kit/sdk/schema'; +import { generateDocumentation, generateERDiagram } from '@graph-kit/sdk/visualization'; import { Command } from 'commander'; import { loadProjectConfig } from './generate.js'; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index bad3068..f69f8ed 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,7 +1,7 @@ -// @graph-om/cli/src/index.ts +// @graph-kit/cli/src/index.ts // CLI entry point -import { formatError } from '@graph-om/sdk/errors'; +import { formatError } from '@graph-kit/sdk/errors'; import { Command } from 'commander'; import { createDiffCommand } from './commands/diff.js'; import { generateCommand } from './commands/generate.js'; @@ -17,13 +17,13 @@ export function createProgram(): Command { const program = new Command(); program - .name('graph-om') - .description('Graph-OM - Prisma-like DX for graph databases') + .name('graph-kit') + .description('Graph-Kit - Prisma-like DX for graph databases') .version(cliVersion()); program .command('init') - .description('Initialize a new Graph-OM project') + .description('Initialize a new Graph-Kit project') .argument('[directory]', 'Project directory', '.') .option('--database ', 'Database type (neo4j)', 'neo4j') .action(initCommand); @@ -45,7 +45,7 @@ export function createProgram(): Command { function isExecutedDirectly(): boolean { const entry = process.argv[1]; if (!entry) return false; - return /[\\/]graph-om$/.test(entry) || /[\\/]index\.(mjs|cjs|js)$/.test(entry); + return /[\\/]graph-kit$/.test(entry) || /[\\/]index\.(mjs|cjs|js)$/.test(entry); } if (isExecutedDirectly()) { diff --git a/packages/cli/src/version.ts b/packages/cli/src/version.ts index 231c273..5d2cfd0 100644 --- a/packages/cli/src/version.ts +++ b/packages/cli/src/version.ts @@ -1,9 +1,9 @@ // The CLI version, injected at build time from packages/cli/package.json (see tsup.config.ts) -declare const __GRAPH_OM_CLI_VERSION__: string | undefined; +declare const __GRAPH_KIT_CLI_VERSION__: string | undefined; export function cliVersion(): string { try { - return typeof __GRAPH_OM_CLI_VERSION__ !== 'undefined' ? __GRAPH_OM_CLI_VERSION__ : '0.0.0'; + return typeof __GRAPH_KIT_CLI_VERSION__ !== 'undefined' ? __GRAPH_KIT_CLI_VERSION__ : '0.0.0'; } catch { return '0.0.0'; } diff --git a/packages/cli/tests/generate.test.ts b/packages/cli/tests/generate.test.ts index 0337245..952081a 100644 --- a/packages/cli/tests/generate.test.ts +++ b/packages/cli/tests/generate.test.ts @@ -1,4 +1,4 @@ -// @graph-om/cli/tests/generate.test.ts +// @graph-kit/cli/tests/generate.test.ts import fs from 'node:fs'; import os from 'node:os'; @@ -19,7 +19,7 @@ import { runGenerate, } from '../src/commands/generate'; -const SCHEMA_FIXTURE = `import { node, relation, schema as sch, string, boolean, date } from '@graph-om/sdk'; +const SCHEMA_FIXTURE = `import { node, relation, schema as sch, string, boolean, date } from '@graph-kit/sdk'; export const User = node('User') .add('id', string({ primary: true })) @@ -46,7 +46,7 @@ export const graph = sch() let tmpDir: string; beforeAll(() => { - tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-om-cli-test-')); + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-kit-cli-test-')); }); afterAll(() => { @@ -107,7 +107,7 @@ describe('loadSchema', () => { const schemaPath = path.join(tmpDir, 'schema-multi.ts'); fs.writeFileSync( schemaPath, - `import { node, relation, string } from '@graph-om/sdk'; + `import { node, relation, string } from '@graph-kit/sdk'; export const A = node('A') .add('id', string({ primary: true })) .add('things', relation('HAS', 'OUT', 'B', { multiple: true })) @@ -173,7 +173,7 @@ describe('content generators', () => { it('generateTypesContent is valid-looking TS with WhereOperator import', () => { const out = generateTypesContent([node]); - expect(out).toContain("import type { WhereOperator } from '@graph-om/sdk';"); + expect(out).toContain("import type { WhereOperator } from '@graph-kit/sdk';"); expect(out).toContain('export interface UserNode'); expect(out).toContain('export type UserCreateInput'); }); @@ -189,7 +189,7 @@ describe('content generators', () => { it('generateClientContent imports neo4j driver and builds node configs', () => { const out = generateClientContent([node]); - expect(out).toContain("import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j';"); + expect(out).toContain("import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j';"); expect(out).toContain('export async function createClient'); expect(out).toContain("label: 'User'"); expect(out).not.toContain('GraphClient.connect'); @@ -206,11 +206,11 @@ describe('loadProjectConfig', () => { expect(config.zod).toBe(false); }); - it('parses graph-om.config.ts via regex', () => { + it('parses graph-kit.config.ts via regex', () => { const dir = path.join(tmpDir, 'ts-config'); fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync( - path.join(dir, 'graph-om.config.ts'), + path.join(dir, 'graph-kit.config.ts'), `export default { schema: './graph/schema.ts', output: { directory: './out', zod: true }, @@ -224,11 +224,11 @@ describe('loadProjectConfig', () => { expect(config.exclude).toEqual(['Internal']); }); - it('parses graph-om.config.json', () => { + it('parses graph-kit.config.json', () => { const dir = path.join(tmpDir, 'json-config'); fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync( - path.join(dir, 'graph-om.config.json'), + path.join(dir, 'graph-kit.config.json'), JSON.stringify({ schema: './s.ts', output: { directory: './gen', zod: true }, @@ -248,7 +248,7 @@ describe('runGenerate', () => { fs.mkdirSync(path.join(dir, 'src'), { recursive: true }); fs.writeFileSync(path.join(dir, 'src', 'schema.ts'), SCHEMA_FIXTURE); fs.writeFileSync( - path.join(dir, 'graph-om.config.ts'), + path.join(dir, 'graph-kit.config.ts'), `export default { schema: './src/schema.ts', output: { directory: './src/__generated__', zod: true } };`, ); diff --git a/packages/cli/tests/init.test.ts b/packages/cli/tests/init.test.ts index f0ae491..29004e2 100644 --- a/packages/cli/tests/init.test.ts +++ b/packages/cli/tests/init.test.ts @@ -1,4 +1,4 @@ -// @graph-om/cli/tests/init.test.ts +// @graph-kit/cli/tests/init.test.ts import fs from 'node:fs'; import os from 'node:os'; @@ -10,7 +10,7 @@ let tmpDir: string; let projectDir: string; beforeAll(async () => { - tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-om-init-test-')); + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-kit-init-test-')); projectDir = path.join(tmpDir, 'my-app'); const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => { throw new Error('process.exit'); @@ -31,19 +31,19 @@ describe('initCommand', () => { it('scaffolds the expected files', () => { expect(fs.existsSync(path.join(projectDir, 'package.json'))).toBe(true); expect(fs.existsSync(path.join(projectDir, 'tsconfig.json'))).toBe(true); - expect(fs.existsSync(path.join(projectDir, 'graph-om.config.ts'))).toBe(true); + expect(fs.existsSync(path.join(projectDir, 'graph-kit.config.ts'))).toBe(true); expect(fs.existsSync(path.join(projectDir, '.env.example'))).toBe(true); expect(fs.existsSync(path.join(projectDir, 'src', 'schema.ts'))).toBe(true); expect(fs.existsSync(path.join(projectDir, 'src', 'index.ts'))).toBe(true); }); - it('writes a package.json with graph-om dependencies and scripts', () => { + it('writes a package.json with graph-kit dependencies and scripts', () => { const pkg = JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json'), 'utf-8')); expect(pkg.name).toBe('my-app'); - expect(pkg.dependencies['@graph-om/sdk']).toBeDefined(); - expect(pkg.dependencies['@graph-om/sdk']).toBeDefined(); - expect(pkg.devDependencies['@graph-om/cli']).toBeDefined(); - expect(pkg.scripts.generate).toBe('graph-om generate'); + expect(pkg.dependencies['@graph-kit/sdk']).toBeDefined(); + expect(pkg.dependencies['@graph-kit/sdk']).toBeDefined(); + expect(pkg.devDependencies['@graph-kit/cli']).toBeDefined(); + expect(pkg.scripts.generate).toBe('graph-kit generate'); }); it('does not call the nonexistent GraphClient.connect', () => { diff --git a/packages/cli/tsup.config.ts b/packages/cli/tsup.config.ts index 914351a..b3ea0fc 100644 --- a/packages/cli/tsup.config.ts +++ b/packages/cli/tsup.config.ts @@ -13,9 +13,9 @@ export default defineConfig({ sourcemap: true, clean: true, treeshake: true, - external: ['@graph-om/sdk'], + external: ['@graph-kit/sdk'], banner: { js: '#!/usr/bin/env node' }, define: { - __GRAPH_OM_CLI_VERSION__: JSON.stringify(pkg.version), + __GRAPH_KIT_CLI_VERSION__: JSON.stringify(pkg.version), }, }); diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts index 85c7a76..ebe6289 100644 --- a/packages/cli/vitest.config.ts +++ b/packages/cli/vitest.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ define: { - __GRAPH_OM_CLI_VERSION__: JSON.stringify('1.0.0'), + __GRAPH_KIT_CLI_VERSION__: JSON.stringify('1.0.0'), }, test: { globals: true, @@ -20,29 +20,29 @@ export default defineConfig({ }, resolve: { alias: [ - // Exact matches only, so '@graph-om/sdk' does not swallow its subpaths + // Exact matches only, so '@graph-kit/sdk' does not swallow its subpaths { - find: /^@graph-om\/sdk$/, + find: /^@graph-kit\/sdk$/, replacement: path.resolve(__dirname, '../sdk/src/index.ts'), }, { - find: /^@graph-om\/sdk\/driver\/(neo4j|memgraph|kuzu|falkordb)$/, + find: /^@graph-kit\/sdk\/driver\/(neo4j|memgraph|kuzu|falkordb)$/, replacement: path.resolve(__dirname, '../sdk/src/driver/$1.ts'), }, { - find: /^@graph-om\/sdk\/(schema|client|query|config|driver|migration|seed|visualization|testing|graphql|batch|auth|observability|otel|benchmark)$/, + find: /^@graph-kit\/sdk\/(schema|client|query|config|driver|migration|seed|visualization|testing|graphql|batch|auth|observability|otel|benchmark)$/, replacement: path.resolve(__dirname, '../sdk/src/$1/index.ts'), }, { - find: '@graph-om/zod', + find: '@graph-kit/zod', replacement: path.resolve(__dirname, '../zod/src/index.ts'), }, { - find: '@graph-om/testing', + find: '@graph-kit/testing', replacement: path.resolve(__dirname, '../testing/src/index.ts'), }, { - find: '@graph-om/migrate', + find: '@graph-kit/migrate', replacement: path.resolve(__dirname, '../migrate/src/index.ts'), }, ], diff --git a/packages/mcp/README.md b/packages/mcp/README.md index 0f939fe..54748c4 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -1,11 +1,11 @@ -# @graph-om/mcp +# @graph-kit/mcp -Graph-OM MCP (Model Context Protocol) server. Exposes graph database operations (run Cypher queries, inspect schema, list nodes and relationships) through the [Model Context Protocol](https://modelcontextprotocol.io/) so AI assistants and MCP clients can interact with your Graph-OM-backed graph database. +Graph-Kit MCP (Model Context Protocol) server. Exposes graph database operations (run Cypher queries, inspect schema, list nodes and relationships) through the [Model Context Protocol](https://modelcontextprotocol.io/) so AI assistants and MCP clients can interact with your Graph-Kit-backed graph database. ## Installation ```bash -pnpm add @graph-om/mcp @graph-om/sdk +pnpm add @graph-kit/mcp @graph-kit/sdk ``` `@modelcontextprotocol/sdk` is a direct dependency and is installed automatically. @@ -13,8 +13,8 @@ pnpm add @graph-om/mcp @graph-om/sdk ## Quick start ```ts -import { createMCPServer } from '@graph-om/mcp'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { createMCPServer } from '@graph-kit/mcp'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; const driver = createNeo4jDriver({ uri: 'bolt://localhost:7687', @@ -26,7 +26,7 @@ await driver.connect(); const server = await createMCPServer({ driver, - name: 'graph-om', + name: 'graph-kit', version: '1.0.0', }); @@ -50,7 +50,7 @@ const server = await createMCPServer({ ## API -### `GraphOMMCPServer` +### `GraphKitMCPServer` Class wrapping an MCP `Server` over stdio. Methods: @@ -61,18 +61,18 @@ Class wrapping an MCP `Server` over stdio. Methods: ### `createMCPServer(config)` -Factory that constructs and configures a `GraphOMMCPServer` with tool, resource, and call handlers. +Factory that constructs and configures a `GraphKitMCPServer` with tool, resource, and call handlers. ```ts -export async function createMCPServer(config: MCPConfig): Promise; +export async function createMCPServer(config: MCPConfig): Promise; ``` ### `MCPConfig` | Field | Type | Description | |-------|------|-------------| -| `driver` | `DriverAdapter \| DriverConfig` | Graph-OM driver adapter or config object | -| `name` | string | Server name (default: `'graph-om'`) | +| `driver` | `DriverAdapter \| DriverConfig` | Graph-Kit driver adapter or config object | +| `name` | string | Server name (default: `'graph-kit'`) | | `version` | string | Server version (default: `'1.0.0'`) | ## MCP capabilities diff --git a/packages/mcp/package.json b/packages/mcp/package.json index fc69a45..6d4de90 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,21 +1,21 @@ { - "name": "@graph-om/mcp", + "name": "@graph-kit/mcp", "version": "0.0.1", - "description": "Graph-OM MCP (Model Context Protocol) server", + "description": "Graph-Kit MCP (Model Context Protocol) server", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git", + "url": "https://github.com/frontal-labs/graph-kit.git", "directory": "packages/mcp" }, - "homepage": "https://github.com/frontal-labs/graph-om/tree/master/packages/mcp#readme", + "homepage": "https://github.com/frontal-labs/graph-kit/tree/master/packages/mcp#readme", "bugs": { - "url": "https://github.com/frontal-labs/graph-om/issues" + "url": "https://github.com/frontal-labs/graph-kit/issues" }, "keywords": [ "mcp", "model-context-protocol", - "graph-om", + "graph-kit", "graph-database" ], "sideEffects": false, @@ -46,7 +46,7 @@ "@modelcontextprotocol/sdk": "^1.32.2" }, "devDependencies": { - "@graph-om/sdk": "workspace:*", + "@graph-kit/sdk": "workspace:*", "@types/node": "^20.10.0", "tsup": "^8.0.0", "typescript": "^5.9.3", diff --git a/packages/mcp/src/config.ts b/packages/mcp/src/config.ts index 9d36505..33f4f80 100644 --- a/packages/mcp/src/config.ts +++ b/packages/mcp/src/config.ts @@ -1,7 +1,7 @@ -// @graph-om/mcp/src/config.ts +// @graph-kit/mcp/src/config.ts // MCP server configuration -import type { AnyDriverConfig, DriverAdapter } from '@graph-om/sdk'; +import type { AnyDriverConfig, DriverAdapter } from '@graph-kit/sdk'; export interface MCPConfig { driver: DriverAdapter | AnyDriverConfig; diff --git a/packages/mcp/src/index.ts b/packages/mcp/src/index.ts index beb3ad6..d820b73 100644 --- a/packages/mcp/src/index.ts +++ b/packages/mcp/src/index.ts @@ -1,5 +1,5 @@ -// @graph-om/mcp/src/index.ts -// Graph-OM MCP (Model Context Protocol) server +// @graph-kit/mcp/src/index.ts +// Graph-Kit MCP (Model Context Protocol) server // Barrel export - manually selects and re-exports public API // Re-exports from MCP SDK @@ -11,7 +11,7 @@ export type { ResourceDefinition } from './resources/index'; // Resources domain export { RESOURCE_DEFINITIONS, readResource } from './resources/index'; // Server domain -export { createMCPServer, GraphOMMCPServer } from './server/mcp-server'; +export { createMCPServer, GraphKitMCPServer } from './server/mcp-server'; export type { ToolDefinition } from './tools/index'; // Tools domain export { callTool, TOOL_DEFINITIONS, toToolError } from './tools/index'; diff --git a/packages/mcp/src/resources/index.ts b/packages/mcp/src/resources/index.ts index e42fb37..cadcce0 100644 --- a/packages/mcp/src/resources/index.ts +++ b/packages/mcp/src/resources/index.ts @@ -1,4 +1,4 @@ -// @graph-om/mcp/src/resources/index.ts +// @graph-kit/mcp/src/resources/index.ts // Resources domain barrel export type { ResourceDefinition } from './resource-handler'; diff --git a/packages/mcp/src/resources/resource-handler.ts b/packages/mcp/src/resources/resource-handler.ts index 88b8868..9c61613 100644 --- a/packages/mcp/src/resources/resource-handler.ts +++ b/packages/mcp/src/resources/resource-handler.ts @@ -1,7 +1,7 @@ -// @graph-om/mcp/src/resources/resource-handler.ts +// @graph-kit/mcp/src/resources/resource-handler.ts // MCP resource definitions and read-resource dispatch logic -import { raiseGraphError } from '@graph-om/sdk/errors'; +import { raiseGraphError } from '@graph-kit/sdk/errors'; export interface ResourceDefinition { uri: string; diff --git a/packages/mcp/src/server/index.ts b/packages/mcp/src/server/index.ts index 098e2d7..cbf373d 100644 --- a/packages/mcp/src/server/index.ts +++ b/packages/mcp/src/server/index.ts @@ -1,4 +1,4 @@ -// @graph-om/mcp/src/server/index.ts +// @graph-kit/mcp/src/server/index.ts // Server domain barrel -export { createMCPServer, GraphOMMCPServer } from './mcp-server'; +export { createMCPServer, GraphKitMCPServer } from './mcp-server'; diff --git a/packages/mcp/src/server/mcp-server.ts b/packages/mcp/src/server/mcp-server.ts index 5158da2..5fa214d 100644 --- a/packages/mcp/src/server/mcp-server.ts +++ b/packages/mcp/src/server/mcp-server.ts @@ -1,8 +1,8 @@ -// @graph-om/mcp/src/server/mcp-server.ts -// Graph-OM MCP server class and factory +// @graph-kit/mcp/src/server/mcp-server.ts +// Graph-Kit MCP server class and factory -import type { AnyDriverConfig, DriverAdapter } from '@graph-om/sdk'; -import { createDriver } from '@graph-om/sdk'; +import type { AnyDriverConfig, DriverAdapter } from '@graph-kit/sdk'; +import { createDriver } from '@graph-kit/sdk'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { @@ -15,7 +15,7 @@ import type { MCPConfig } from '../config'; import { RESOURCE_DEFINITIONS, readResource } from '../resources/index'; import { callTool, TOOL_DEFINITIONS, toToolError } from '../tools/index'; -export class GraphOMMCPServer { +export class GraphKitMCPServer { private server: Server; private driver: DriverAdapter; @@ -27,7 +27,7 @@ export class GraphOMMCPServer { this.server = new Server( { - name: config.name ?? 'graph-om', + name: config.name ?? 'graph-kit', version: config.version ?? '1.0.0', }, { @@ -71,7 +71,7 @@ export class GraphOMMCPServer { await this.driver.connect(); const transport = new StdioServerTransport(); await this.server.connect(transport); - console.error('Graph-OM MCP Server running on stdio'); + console.error('Graph-Kit MCP Server running on stdio'); } async stop(): Promise { @@ -80,7 +80,7 @@ export class GraphOMMCPServer { } } -export async function createMCPServer(config: MCPConfig): Promise { - const server = new GraphOMMCPServer(config); +export async function createMCPServer(config: MCPConfig): Promise { + const server = new GraphKitMCPServer(config); return server; } diff --git a/packages/mcp/src/tools/index.ts b/packages/mcp/src/tools/index.ts index 5c0290c..010df0e 100644 --- a/packages/mcp/src/tools/index.ts +++ b/packages/mcp/src/tools/index.ts @@ -1,4 +1,4 @@ -// @graph-om/mcp/src/tools/index.ts +// @graph-kit/mcp/src/tools/index.ts // Tools domain barrel export { toToolError } from './tool-error'; diff --git a/packages/mcp/src/tools/tool-error.ts b/packages/mcp/src/tools/tool-error.ts index 92f8cff..692deda 100644 --- a/packages/mcp/src/tools/tool-error.ts +++ b/packages/mcp/src/tools/tool-error.ts @@ -1,7 +1,7 @@ -// @graph-om/mcp/src/tools/tool-error.ts +// @graph-kit/mcp/src/tools/tool-error.ts // Converts errors into client-safe MCP tool error results -import { errorResponse, toPublic } from '@graph-om/sdk/errors'; +import { errorResponse, toPublic } from '@graph-kit/sdk/errors'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; export function toToolError(error: unknown): CallToolResult { diff --git a/packages/mcp/src/tools/tool-handler.ts b/packages/mcp/src/tools/tool-handler.ts index 0581de6..c6b3b46 100644 --- a/packages/mcp/src/tools/tool-handler.ts +++ b/packages/mcp/src/tools/tool-handler.ts @@ -1,8 +1,8 @@ -// @graph-om/mcp/src/tools/tool-handler.ts +// @graph-kit/mcp/src/tools/tool-handler.ts // MCP tool definitions and call-tool dispatch logic -import type { DriverAdapter } from '@graph-om/sdk'; -import { raiseGraphError } from '@graph-om/sdk/errors'; +import type { DriverAdapter } from '@graph-kit/sdk'; +import { raiseGraphError } from '@graph-kit/sdk/errors'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; export interface ToolDefinition { diff --git a/packages/mcp/tests/server.test.ts b/packages/mcp/tests/server.test.ts index d4ae8c2..e54f6f5 100644 --- a/packages/mcp/tests/server.test.ts +++ b/packages/mcp/tests/server.test.ts @@ -1,15 +1,15 @@ -import { createMockDriver } from '@graph-om/sdk/testing'; +import { createMockDriver } from '@graph-kit/sdk/testing'; import { describe, expect, it } from 'vitest'; -import { createMCPServer, GraphOMMCPServer } from '../src/index.js'; +import { createMCPServer, GraphKitMCPServer } from '../src/index.js'; -describe('GraphOMMCPServer', () => { +describe('GraphKitMCPServer', () => { it('builds a server around a driver adapter instance', () => { - const server = new GraphOMMCPServer({ driver: createMockDriver(), name: 'test-graph' }); - expect(server).toBeInstanceOf(GraphOMMCPServer); + const server = new GraphKitMCPServer({ driver: createMockDriver(), name: 'test-graph' }); + expect(server).toBeInstanceOf(GraphKitMCPServer); }); it('creates a server through the async factory', async () => { const server = await createMCPServer({ driver: createMockDriver() }); - expect(server).toBeInstanceOf(GraphOMMCPServer); + expect(server).toBeInstanceOf(GraphKitMCPServer); }); }); diff --git a/packages/mcp/tsup.config.ts b/packages/mcp/tsup.config.ts index caf86c5..728f3e6 100644 --- a/packages/mcp/tsup.config.ts +++ b/packages/mcp/tsup.config.ts @@ -8,8 +8,8 @@ export default defineConfig({ sourcemap: true, clean: true, treeshake: true, - external: ['@modelcontextprotocol/sdk', '@graph-om/sdk'], + external: ['@modelcontextprotocol/sdk', '@graph-kit/sdk'], banner: { - js: '// @graph-om/mcp - Graph-OM MCP (Model Context Protocol) server', + js: '// @graph-kit/mcp - Graph-Kit MCP (Model Context Protocol) server', }, }); diff --git a/packages/migrate/README.md b/packages/migrate/README.md index 27d4a62..cd3792d 100644 --- a/packages/migrate/README.md +++ b/packages/migrate/README.md @@ -1,19 +1,19 @@ -# @graph-om/migrate +# @graph-kit/migrate -Graph-OM migration system — schema versioning and database migrations for graph databases. Provides a `MigrationRunner` that applies and rolls back Cypher migrations, tracks applied migrations as `Migration` nodes in the graph, and can generate migrations from schema diffs. +Graph-Kit migration system — schema versioning and database migrations for graph databases. Provides a `MigrationRunner` that applies and rolls back Cypher migrations, tracks applied migrations as `Migration` nodes in the graph, and can generate migrations from schema diffs. ## Installation ```bash -pnpm add @graph-om/migrate @graph-om/sdk +pnpm add @graph-kit/migrate @graph-kit/sdk ``` ## Quick start ```ts -import { MigrationRunner, generateVersion } from '@graph-om/migrate'; -import { QueryCompiler } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { MigrationRunner, generateVersion } from '@graph-kit/migrate'; +import { QueryCompiler } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; const driver = createNeo4jDriver({ uri, username, password }); await driver.connect(); @@ -21,7 +21,7 @@ await driver.connect(); const runner = new MigrationRunner({ driver, migrationsDir: './migrations', - tableName: '_graph_om_migrations', + tableName: '_graph_kit_migrations', }); await runner.initialize(); @@ -79,10 +79,10 @@ export class MigrationRunner { | Field | Type | Default | Description | |-------|------|---------|-------------| -| `driver` | `DriverAdapter` | yes | Graph-OM driver adapter | +| `driver` | `DriverAdapter` | yes | Graph-Kit driver adapter | | `schema` | `GraphSchemaRegistry` | no | Optional schema registry for diffing | | `migrationsDir` | string | `'./migrations'` | Directory containing migration files | -| `tableName` | string | `'_graph_om_migrations'` | Migrations tracking node/table name | +| `tableName` | string | `'_graph_kit_migrations'` | Migrations tracking node/table name | ### `Migration` diff --git a/packages/migrate/package.json b/packages/migrate/package.json index 9775c13..b651de4 100644 --- a/packages/migrate/package.json +++ b/packages/migrate/package.json @@ -1,22 +1,22 @@ { - "name": "@graph-om/migrate", + "name": "@graph-kit/migrate", "version": "0.0.1", - "description": "Graph-OM migration system - schema versioning and database migrations", + "description": "Graph-Kit migration system - schema versioning and database migrations", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git", + "url": "https://github.com/frontal-labs/graph-kit.git", "directory": "packages/migrate" }, - "homepage": "https://github.com/frontal-labs/graph-om/tree/master/packages/migrate#readme", + "homepage": "https://github.com/frontal-labs/graph-kit/tree/master/packages/migrate#readme", "bugs": { - "url": "https://github.com/frontal-labs/graph-om/issues" + "url": "https://github.com/frontal-labs/graph-kit/issues" }, "keywords": [ "migration", "schema", "versioning", - "graph-om" + "graph-kit" ], "sideEffects": false, "files": [ @@ -44,7 +44,7 @@ }, "dependencies": {}, "devDependencies": { - "@graph-om/sdk": "workspace:*", + "@graph-kit/sdk": "workspace:*", "@types/node": "^20.10.0", "tsup": "^8.0.0", "typescript": "^5.9.3", diff --git a/packages/migrate/src/index.ts b/packages/migrate/src/index.ts index 6cecc0e..2f5f6d8 100644 --- a/packages/migrate/src/index.ts +++ b/packages/migrate/src/index.ts @@ -1,5 +1,5 @@ -// @graph-om/migrate/src/index.ts -// Graph-OM migration system - schema versioning and database migrations +// @graph-kit/migrate/src/index.ts +// Graph-Kit migration system - schema versioning and database migrations // Barrel export - manually selects and re-exports public API // Model domain diff --git a/packages/migrate/src/model/index.ts b/packages/migrate/src/model/index.ts index 105b4b2..a2e15ea 100644 --- a/packages/migrate/src/model/index.ts +++ b/packages/migrate/src/model/index.ts @@ -1,4 +1,4 @@ -// @graph-om/migrate/src/model/index.ts +// @graph-kit/migrate/src/model/index.ts // Model domain barrel export type { CreateMigrationOptions, Migration } from './migration'; diff --git a/packages/migrate/src/model/migration.ts b/packages/migrate/src/model/migration.ts index e1d6285..4f4f86b 100644 --- a/packages/migrate/src/model/migration.ts +++ b/packages/migrate/src/model/migration.ts @@ -1,7 +1,7 @@ -// @graph-om/migrate/src/model/migration.ts +// @graph-kit/migrate/src/model/migration.ts // Migration model interfaces -import type { GraphSchemaRegistry, QueryCompiler } from '@graph-om/sdk'; +import type { GraphSchemaRegistry, QueryCompiler } from '@graph-kit/sdk'; export interface Migration { version: string; diff --git a/packages/migrate/src/runner/index.ts b/packages/migrate/src/runner/index.ts index cb76439..b7d7e54 100644 --- a/packages/migrate/src/runner/index.ts +++ b/packages/migrate/src/runner/index.ts @@ -1,4 +1,4 @@ -// @graph-om/migrate/src/runner/index.ts +// @graph-kit/migrate/src/runner/index.ts // Runner domain barrel export type { MigrationOptions, MigrationStatus } from './migration-options'; diff --git a/packages/migrate/src/runner/migration-options.ts b/packages/migrate/src/runner/migration-options.ts index fac69df..627efe9 100644 --- a/packages/migrate/src/runner/migration-options.ts +++ b/packages/migrate/src/runner/migration-options.ts @@ -1,7 +1,7 @@ -// @graph-om/migrate/src/runner/migration-options.ts +// @graph-kit/migrate/src/runner/migration-options.ts // Migration runner options and status types -import type { DriverAdapter, GraphSchemaRegistry } from '@graph-om/sdk'; +import type { DriverAdapter, GraphSchemaRegistry } from '@graph-kit/sdk'; export interface MigrationOptions { migrationsDir?: string; diff --git a/packages/migrate/src/runner/migration-runner.ts b/packages/migrate/src/runner/migration-runner.ts index cee89aa..d62a251 100644 --- a/packages/migrate/src/runner/migration-runner.ts +++ b/packages/migrate/src/runner/migration-runner.ts @@ -1,9 +1,9 @@ -// @graph-om/migrate/src/runner/migration-runner.ts +// @graph-kit/migrate/src/runner/migration-runner.ts // Migration execution engine - applies, rolls back, and reports migration status -import type { DriverAdapter } from '@graph-om/sdk'; -import { QueryCompiler } from '@graph-om/sdk'; -import { raiseGraphError } from '@graph-om/sdk/errors'; +import type { DriverAdapter } from '@graph-kit/sdk'; +import { QueryCompiler } from '@graph-kit/sdk'; +import { raiseGraphError } from '@graph-kit/sdk/errors'; import type { Migration } from '../model/migration'; import type { MigrationOptions, MigrationStatus } from './migration-options'; @@ -12,13 +12,13 @@ export class MigrationRunner { private compiler: QueryCompiler; private migrationsDir: string; private tableName: string; - private schema?: import('@graph-om/sdk').GraphSchemaRegistry; + private schema?: import('@graph-kit/sdk').GraphSchemaRegistry; constructor(options: MigrationOptions) { this.driver = options.driver; this.compiler = new QueryCompiler(); this.migrationsDir = options.migrationsDir ?? './migrations'; - this.tableName = options.tableName ?? '_graph_om_migrations'; + this.tableName = options.tableName ?? '_graph_kit_migrations'; this.schema = options.schema; } diff --git a/packages/migrate/src/schema/index.ts b/packages/migrate/src/schema/index.ts index 374bcf2..eacbff2 100644 --- a/packages/migrate/src/schema/index.ts +++ b/packages/migrate/src/schema/index.ts @@ -1,4 +1,4 @@ -// @graph-om/migrate/src/schema/index.ts +// @graph-kit/migrate/src/schema/index.ts // Schema domain barrel export type { NodeDiff, PropertyDiff, SchemaDiff } from './schema-diff'; diff --git a/packages/migrate/src/schema/schema-diff.ts b/packages/migrate/src/schema/schema-diff.ts index 6d3a762..5287511 100644 --- a/packages/migrate/src/schema/schema-diff.ts +++ b/packages/migrate/src/schema/schema-diff.ts @@ -1,7 +1,7 @@ -// @graph-om/migrate/src/schema/schema-diff.ts +// @graph-kit/migrate/src/schema/schema-diff.ts // Schema diffing and migration generation from diffs -import type { GraphSchemaRegistry, QueryCompiler } from '@graph-om/sdk'; +import type { GraphSchemaRegistry, QueryCompiler } from '@graph-kit/sdk'; import type { Migration } from '../model/migration'; import { generateVersion } from '../version/version'; diff --git a/packages/migrate/src/template/index.ts b/packages/migrate/src/template/index.ts index fd053e8..a316a29 100644 --- a/packages/migrate/src/template/index.ts +++ b/packages/migrate/src/template/index.ts @@ -1,4 +1,4 @@ -// @graph-om/migrate/src/template/index.ts +// @graph-kit/migrate/src/template/index.ts // Template domain barrel export type { CreateMigrationTemplateOptions } from './migration-template'; diff --git a/packages/migrate/src/template/migration-template.ts b/packages/migrate/src/template/migration-template.ts index 09701bf..9dd1fa4 100644 --- a/packages/migrate/src/template/migration-template.ts +++ b/packages/migrate/src/template/migration-template.ts @@ -1,7 +1,7 @@ -// @graph-om/migrate/src/template/migration-template.ts +// @graph-kit/migrate/src/template/migration-template.ts // Migration file template generation -import type { GraphSchemaRegistry } from '@graph-om/sdk'; +import type { GraphSchemaRegistry } from '@graph-kit/sdk'; import { generateVersion } from '../version/version'; export interface CreateMigrationTemplateOptions { @@ -15,8 +15,8 @@ export function createMigrationTemplate(options: CreateMigrationTemplateOptions) // Version: ${generateVersion()} // Created: ${new Date().toISOString()} -import { QueryCompiler } from '@graph-om/sdk'; -import type { Migration } from '@graph-om/migrate'; +import { QueryCompiler } from '@graph-kit/sdk'; +import type { Migration } from '@graph-kit/migrate'; export const migration: Migration = { version: '${generateVersion()}', diff --git a/packages/migrate/src/version/index.ts b/packages/migrate/src/version/index.ts index f6a1dc7..1442bbe 100644 --- a/packages/migrate/src/version/index.ts +++ b/packages/migrate/src/version/index.ts @@ -1,4 +1,4 @@ -// @graph-om/migrate/src/version/index.ts +// @graph-kit/migrate/src/version/index.ts // Version domain barrel export { generateVersion } from './version'; diff --git a/packages/migrate/src/version/version.ts b/packages/migrate/src/version/version.ts index 12f348a..c63e668 100644 --- a/packages/migrate/src/version/version.ts +++ b/packages/migrate/src/version/version.ts @@ -1,4 +1,4 @@ -// @graph-om/migrate/src/version/version.ts +// @graph-kit/migrate/src/version/version.ts // Migration version generation export function generateVersion(): string { diff --git a/packages/migrate/tests/runner.test.ts b/packages/migrate/tests/runner.test.ts index fced8e7..7013d7a 100644 --- a/packages/migrate/tests/runner.test.ts +++ b/packages/migrate/tests/runner.test.ts @@ -1,4 +1,4 @@ -import { createMockDriver } from '@graph-om/sdk/testing'; +import { createMockDriver } from '@graph-kit/sdk/testing'; import { describe, expect, it } from 'vitest'; import { type Migration, MigrationRunner } from '../src/index.js'; diff --git a/packages/migrate/tsup.config.ts b/packages/migrate/tsup.config.ts index ba04678..c32a98a 100644 --- a/packages/migrate/tsup.config.ts +++ b/packages/migrate/tsup.config.ts @@ -8,8 +8,8 @@ export default defineConfig({ sourcemap: true, clean: true, treeshake: true, - external: ['@graph-om/sdk'], + external: ['@graph-kit/sdk'], banner: { - js: '// @graph-om/migrate - Graph-OM migration system', + js: '// @graph-kit/migrate - Graph-Kit migration system', }, }); diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 08018b3..a8c931c 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -1,27 +1,27 @@ -# @graph-om/sdk +# @graph-kit/sdk -Graph-OM - Prisma-like developer experience for graph databases. The core SDK provides the schema DSL, Cypher query compiler, typed `GraphClient`, driver abstraction, configuration, migrations, observability, OpenTelemetry, GraphQL, batch operations, seeding, testing utilities, visualization, and auth. +Graph-Kit - Prisma-like developer experience for graph databases. The core SDK provides the schema DSL, Cypher query compiler, typed `GraphClient`, driver abstraction, configuration, migrations, observability, OpenTelemetry, GraphQL, batch operations, seeding, testing utilities, visualization, and auth. ## Installation ```bash -pnpm add @graph-om/sdk +pnpm add @graph-kit/sdk ``` Drivers ship with the SDK. Import the one for your database from its subpath: ```ts -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; // Neo4j -import { createMemgraphDriver } from '@graph-om/sdk/driver/memgraph'; // Memgraph -import { createKuzuDriverAsync } from '@graph-om/sdk/driver'; // Kuzu (embedded), async factory -import { createFalkorDBDriver } from '@graph-om/sdk/driver/falkordb'; // FalkorDB +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; // Neo4j +import { createMemgraphDriver } from '@graph-kit/sdk/driver/memgraph'; // Memgraph +import { createKuzuDriverAsync } from '@graph-kit/sdk/driver'; // Kuzu (embedded), async factory +import { createFalkorDBDriver } from '@graph-kit/sdk/driver/falkordb'; // FalkorDB ``` ## Quick start ```ts -import { node, relation, string, GraphClient } from '@graph-om/sdk'; -import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j'; +import { node, relation, string, GraphClient } from '@graph-kit/sdk'; +import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j'; // 1. Define your schema with the DSL export const User = node('User') @@ -62,24 +62,24 @@ await driver.disconnect(); | Export | Contents | |--------|----------| -| `@graph-om/sdk` | Everything (schema, client, query, driver, config, migration, observability, otel, graphql, batch, seed, testing, visualization, auth, benchmark, types) | -| `@graph-om/sdk/schema` | Schema builders: `node`, `relation`, `schema`, `string`, `number`, `boolean`, `date`, `float`, `bigint`, `uuid`, `json`, `path`, `property`, `allShortestPaths`, `shortestPath`, parsers | -| `@graph-om/sdk/client` | `GraphClient`, `GraphTransaction`, value helpers | -| `@graph-om/sdk/errors` | `GraphError`, `raiseGraphError`, `hasCode`, `isRetryable`, `isFrontalError`, `getRootCause`, `mapDriverError`, `toPublic`, `errorResponse`, `formatError` | -| `@graph-om/sdk/query` | `QueryCompiler`, `createQueryCompiler`, `CompiledQuery` | -| `@graph-om/sdk/config` | `defineConfig`, `loadConfig`, `resolveConfig`, `getDefaultConfig`, `env` | -| `@graph-om/sdk/driver` | `DriverAdapter`, `DriverCapabilities`, `DriverConfig`, `createDriver`, `registerDriver`, `listDrivers`, `getDriverFactory`, config types (`Neo4jDriverConfig`, `MemgraphDriverConfig`, `FalkorDBDriverConfig`, `AnyDriverConfig`), `QueryResult`, `QueryRecord`, `TransactionContext` | -| `@graph-om/sdk/migration` | `MigrationRunner`, `createMigrationRunner`, `Migration`, `MigrationStatus`, `SchemaDiff`, `NodeDiff`, `PropertyDiff`, `RelationDiff`, `diffSchemas`, `generateMigrationFromDiff`, `createMigrationTemplate`, `generateVersion`, `loadMigrations` | -| `@graph-om/sdk/observability` | `QueryLogger`, `QueryProfiler`, `PrometheusMetricsCollector`, logging/tracing/metrics adapters | -| `@graph-om/sdk/otel` | OpenTelemetry instrumentation: `initializeOTel`, `TracedDriverAdapter`, `createOTelMiddleware`, tracers, meters, spans | -| `@graph-om/sdk/graphql` | `generateGraphQLSchema`, `generateResolvers`, Apollo/Yoga configs, scalars | -| `@graph-om/sdk/batch` | `BatchProcessor`, `createBatchProcessor`, bulk insert/update/delete/relate, CSV/JSON import/export | -| `@graph-om/sdk/seed` | `SeedManager`, `createSeedManager`, factories, CSV/JSON seed loading | -| `@graph-om/sdk/testing` | `MockDriverAdapter`, `createMockDriver`, `graphMatchers`, `createTestFixtures`, `generateTestData`, random generators | -| `@graph-om/sdk/visualization` | `generateERDiagram`, `generateDocumentation`, `exportSchema` | -| `@graph-om/sdk/auth` | `AuthManager`, `createAuthManager`, roles, permissions, sessions, tokens | -| `@graph-om/sdk/benchmark` | `BenchmarkRunner`, benchmark suites, CI regression detection | -| `@graph-om/sdk/schema/parser` | `parseSchemaFile`, `parseSchemaFromSource` | +| `@graph-kit/sdk` | Everything (schema, client, query, driver, config, migration, observability, otel, graphql, batch, seed, testing, visualization, auth, benchmark, types) | +| `@graph-kit/sdk/schema` | Schema builders: `node`, `relation`, `schema`, `string`, `number`, `boolean`, `date`, `float`, `bigint`, `uuid`, `json`, `path`, `property`, `allShortestPaths`, `shortestPath`, parsers | +| `@graph-kit/sdk/client` | `GraphClient`, `GraphTransaction`, value helpers | +| `@graph-kit/sdk/errors` | `GraphError`, `raiseGraphError`, `hasCode`, `isRetryable`, `isFrontalError`, `getRootCause`, `mapDriverError`, `toPublic`, `errorResponse`, `formatError` | +| `@graph-kit/sdk/query` | `QueryCompiler`, `createQueryCompiler`, `CompiledQuery` | +| `@graph-kit/sdk/config` | `defineConfig`, `loadConfig`, `resolveConfig`, `getDefaultConfig`, `env` | +| `@graph-kit/sdk/driver` | `DriverAdapter`, `DriverCapabilities`, `DriverConfig`, `createDriver`, `registerDriver`, `listDrivers`, `getDriverFactory`, config types (`Neo4jDriverConfig`, `MemgraphDriverConfig`, `FalkorDBDriverConfig`, `AnyDriverConfig`), `QueryResult`, `QueryRecord`, `TransactionContext` | +| `@graph-kit/sdk/migration` | `MigrationRunner`, `createMigrationRunner`, `Migration`, `MigrationStatus`, `SchemaDiff`, `NodeDiff`, `PropertyDiff`, `RelationDiff`, `diffSchemas`, `generateMigrationFromDiff`, `createMigrationTemplate`, `generateVersion`, `loadMigrations` | +| `@graph-kit/sdk/observability` | `QueryLogger`, `QueryProfiler`, `PrometheusMetricsCollector`, logging/tracing/metrics adapters | +| `@graph-kit/sdk/otel` | OpenTelemetry instrumentation: `initializeOTel`, `TracedDriverAdapter`, `createOTelMiddleware`, tracers, meters, spans | +| `@graph-kit/sdk/graphql` | `generateGraphQLSchema`, `generateResolvers`, Apollo/Yoga configs, scalars | +| `@graph-kit/sdk/batch` | `BatchProcessor`, `createBatchProcessor`, bulk insert/update/delete/relate, CSV/JSON import/export | +| `@graph-kit/sdk/seed` | `SeedManager`, `createSeedManager`, factories, CSV/JSON seed loading | +| `@graph-kit/sdk/testing` | `MockDriverAdapter`, `createMockDriver`, `graphMatchers`, `createTestFixtures`, `generateTestData`, random generators | +| `@graph-kit/sdk/visualization` | `generateERDiagram`, `generateDocumentation`, `exportSchema` | +| `@graph-kit/sdk/auth` | `AuthManager`, `createAuthManager`, roles, permissions, sessions, tokens | +| `@graph-kit/sdk/benchmark` | `BenchmarkRunner`, benchmark suites, CI regression detection | +| `@graph-kit/sdk/schema/parser` | `parseSchemaFile`, `parseSchemaFromSource` | ## Core concepts @@ -88,7 +88,7 @@ await driver.disconnect(); Define nodes and relations with type-safe builders: ```ts -import { node, relation, string, number, boolean, date, uuid, json } from '@graph-om/sdk/schema'; +import { node, relation, string, number, boolean, date, uuid, json } from '@graph-kit/sdk/schema'; const User = node('User') .add('id', uuid({ primary: true })) @@ -108,7 +108,7 @@ Property options include `primary`, `unique`, `nullable`, `array`, `default`, an Compile Cypher programmatically: ```ts -import { QueryCompiler } from '@graph-om/sdk/query'; +import { QueryCompiler } from '@graph-kit/sdk/query'; const compiler = new QueryCompiler(); const { cypher, params } = compiler.compileFind('User', { where: { name: 'Alice' } }); @@ -133,17 +133,17 @@ await client.upsert('User', { where: { id: 'u1' }, create: {}, update: {} }); ### Driver abstraction -Graph-OM abstracts database drivers behind `DriverAdapter`. Built-in drivers live under the SDK's `driver` subpaths: +Graph-Kit abstracts database drivers behind `DriverAdapter`. Built-in drivers live under the SDK's `driver` subpaths: -- `@graph-om/sdk/driver/neo4j` — Neo4j (Bolt) -- `@graph-om/sdk/driver/memgraph` — Memgraph (Bolt-compatible) -- `@graph-om/sdk/driver` (`createKuzuDriverAsync`) — Kuzu (embedded) -- `@graph-om/sdk/driver/falkordb` — FalkorDB (RedisGraph) +- `@graph-kit/sdk/driver/neo4j` — Neo4j (Bolt) +- `@graph-kit/sdk/driver/memgraph` — Memgraph (Bolt-compatible) +- `@graph-kit/sdk/driver` (`createKuzuDriverAsync`) — Kuzu (embedded) +- `@graph-kit/sdk/driver/falkordb` — FalkorDB (RedisGraph) Register a custom driver: ```ts -import { registerDriver, createDriver } from '@graph-om/sdk/driver'; +import { registerDriver, createDriver } from '@graph-kit/sdk/driver'; registerDriver('my-db', MyDriverAdapter); const driver = createDriver({ type: 'my-db', ...config }); @@ -151,10 +151,10 @@ const driver = createDriver({ type: 'my-db', ...config }); ## Handling errors -Every failure graph-om throws is a typed `GraphError` with a stable `code`, so you can branch on it rather than on the message: +Every failure graph-kit throws is a typed `GraphError` with a stable `code`, so you can branch on it rather than on the message: ```ts -import { hasCode } from '@graph-om/sdk/errors'; +import { hasCode } from '@graph-kit/sdk/errors'; try { await client.update('Person', { where: { id }, data }); @@ -166,12 +166,12 @@ try { } ``` -Driver errors keep the original error on `cause`. Before sending an error to a client, convert it with `toPublic`, so the client sees only the code and a fixed message. See [docs/errors.md](https://github.com/frontal-labs/graph-om/blob/main/docs/errors.md) for every code. +Driver errors keep the original error on `cause`. Before sending an error to a client, convert it with `toPublic`, so the client sees only the code and a fixed message. See [docs/errors.md](https://github.com/frontal-labs/graph-kit/blob/main/docs/errors.md) for every code. ## Configuration ```ts -import { defineConfig, loadConfig } from '@graph-om/sdk/config'; +import { defineConfig, loadConfig } from '@graph-kit/sdk/config'; const config = defineConfig({ database: { @@ -190,19 +190,19 @@ Environment-driven config is supported via `env` (powered by `@t3-oss/env-core`) ## Observability & OpenTelemetry ```ts -import { QueryLogger, QueryProfiler, initializeOTel, TracedDriverAdapter } from '@graph-om/sdk'; +import { QueryLogger, QueryProfiler, initializeOTel, TracedDriverAdapter } from '@graph-kit/sdk'; const logger = createQueryLogger(); const profiler = createQueryProfiler(); -initializeOTel({ serviceName: 'graph-om' }); +initializeOTel({ serviceName: 'graph-kit' }); const tracedDriver = new TracedDriverAdapter(driver); ``` ## Testing ```ts -import { createMockDriver, graphMatchers, createTestFixtures, generateTestData } from '@graph-om/sdk/testing'; +import { createMockDriver, graphMatchers, createTestFixtures, generateTestData } from '@graph-kit/sdk/testing'; const mock = createMockDriver(); const client = new GraphClient(mock, graph); diff --git a/packages/sdk/THIRD_PARTY_NOTICES.md b/packages/sdk/THIRD_PARTY_NOTICES.md index cc7e14f..b954e94 100644 --- a/packages/sdk/THIRD_PARTY_NOTICES.md +++ b/packages/sdk/THIRD_PARTY_NOTICES.md @@ -1,6 +1,6 @@ # Third-party notices -`@graph-om/sdk` bundles `@frontal-labs/error@0.7.0` (MIT License, Copyright (c) 2026 Frontal Labs, Inc.) into its ESM and CJS builds, so that the SDK works under CommonJS and on Node 22. The bundled code is unmodified. +`@graph-kit/sdk` bundles `@frontal-labs/error@0.7.0` (MIT License, Copyright (c) 2026 Frontal Labs, Inc.) into its ESM and CJS builds, so that the SDK works under CommonJS and on Node 22. The bundled code is unmodified. The full license text follows. diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 5f63f54..bb33756 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,16 +1,16 @@ { - "name": "@graph-om/sdk", + "name": "@graph-kit/sdk", "version": "0.0.1", - "description": "Graph-OM - Prisma-like DX for graph databases", + "description": "Graph-Kit - Prisma-like DX for graph databases", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git", + "url": "https://github.com/frontal-labs/graph-kit.git", "directory": "packages/sdk" }, - "homepage": "https://github.com/frontal-labs/graph-om/tree/master/packages/sdk#readme", + "homepage": "https://github.com/frontal-labs/graph-kit/tree/master/packages/sdk#readme", "bugs": { - "url": "https://github.com/frontal-labs/graph-om/issues" + "url": "https://github.com/frontal-labs/graph-kit/issues" }, "keywords": [ "ogm", diff --git a/packages/sdk/src/auth/index.ts b/packages/sdk/src/auth/index.ts index e2b356b..8caa007 100644 --- a/packages/sdk/src/auth/index.ts +++ b/packages/sdk/src/auth/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/auth/index.ts -// Authentication and authorization helpers for Graph-OM +// @graph-kit/sdk/src/auth/index.ts +// Authentication and authorization helpers for Graph-Kit import { GraphClient } from '../client'; import { raiseGraphError } from '../errors'; diff --git a/packages/sdk/src/batch/index.ts b/packages/sdk/src/batch/index.ts index 19d4310..e3e3c78 100644 --- a/packages/sdk/src/batch/index.ts +++ b/packages/sdk/src/batch/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/batch/index.ts -// Batch operations and bulk import for Graph-OM +// @graph-kit/sdk/src/batch/index.ts +// Batch operations and bulk import for Graph-Kit import type { AnyNodeConfig, DriverAdapter, GraphSchemaRegistry, QueryResult } from '../types'; diff --git a/packages/sdk/src/benchmark/index.ts b/packages/sdk/src/benchmark/index.ts index e15bde2..46bfdfb 100644 --- a/packages/sdk/src/benchmark/index.ts +++ b/packages/sdk/src/benchmark/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/benchmark/index.ts -// Benchmark suite for Graph-OM - performance testing and regression detection +// @graph-kit/sdk/src/benchmark/index.ts +// Benchmark suite for Graph-Kit - performance testing and regression detection import fs from 'node:fs'; import path from 'node:path'; @@ -287,7 +287,7 @@ export function createBenchmarkRunner(config?: BaselineConfig): BenchmarkRunner return new BenchmarkRunner(config); } -// Pre-defined benchmarks for Graph-OM +// Pre-defined benchmarks for Graph-Kit export const graphBenchmarks = { async createNode(driver: DriverAdapter, label: string, count: number): Promise { // Index the id lookups used by every later benchmark step; without it each MATCH scans the label diff --git a/packages/sdk/src/client/index.ts b/packages/sdk/src/client/index.ts index 637e661..6f83005 100644 --- a/packages/sdk/src/client/index.ts +++ b/packages/sdk/src/client/index.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/client/index.ts +// @graph-kit/sdk/src/client/index.ts // GraphClient - Type-safe graph database client import { raiseGraphError } from '../errors'; @@ -57,7 +57,7 @@ export class GraphClient { * * @example * ```ts - * import { createNeo4jDriver } from '@graph-om/sdk/driver/neo4j' + * import { createNeo4jDriver } from '@graph-kit/sdk/driver/neo4j' * const client = GraphClient.fromConfig(driver, { schema: './src/schema.ts' }) * ``` */ diff --git a/packages/sdk/src/config/index.ts b/packages/sdk/src/config/index.ts index 3a9043c..4c2b34d 100644 --- a/packages/sdk/src/config/index.ts +++ b/packages/sdk/src/config/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/config/index.ts -// Graph-OM configuration system — inspired by Vite's defineConfig, Prisma schema, Drizzle config +// @graph-kit/sdk/src/config/index.ts +// Graph-Kit configuration system — inspired by Vite's defineConfig, Prisma schema, Drizzle config import type { GraphConfig, GraphDriverConfig, GraphOutputConfig } from '../types'; @@ -36,7 +36,8 @@ export function resolveConfig( /** * Try to load a config file from the project root. - * Supports graph-om.config.ts, graph-om.config.mjs, graph-om.config.js, graph-om.config.json. + * Supports graph.config.ts (preferred), graph.config.mjs, graph.config.js, graph.config.json, + * and the legacy graph-kit.config.* names. */ export async function loadConfig(cwd?: string): Promise { const path = await import('node:path'); @@ -44,10 +45,14 @@ export async function loadConfig(cwd?: string): Promise { const root = cwd ?? process.cwd(); const candidates = [ - 'graph-om.config.ts', - 'graph-om.config.mjs', - 'graph-om.config.js', - 'graph-om.config.json', + 'graph.config.ts', + 'graph.config.mjs', + 'graph.config.js', + 'graph.config.json', + 'graph-kit.config.ts', + 'graph-kit.config.mjs', + 'graph-kit.config.js', + 'graph-kit.config.json', ]; for (const file of candidates) { diff --git a/packages/sdk/src/config/keys.ts b/packages/sdk/src/config/keys.ts index 7896241..3f5576a 100644 --- a/packages/sdk/src/config/keys.ts +++ b/packages/sdk/src/config/keys.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/config/keys.ts +// @graph-kit/sdk/src/config/keys.ts // Validated environment variables powered by @t3-oss/env-core + zod. // All process.env values are parsed through this single schema, so the app // fails fast on missing/invalid config instead of silently using undefined. @@ -12,7 +12,7 @@ export const env = createEnv({ NEO4J_USER: z.string().default('neo4j'), NEO4J_PASSWORD: z.string().default('password'), NEO4J_DATABASE: z.string().optional(), - GRAPH_OM_DEBUG: z + GRAPH_KIT_DEBUG: z .string() .optional() .transform((val) => val === 'true'), diff --git a/packages/sdk/src/driver/falkordb.ts b/packages/sdk/src/driver/falkordb.ts index 43dd06d..52f19fa 100644 --- a/packages/sdk/src/driver/falkordb.ts +++ b/packages/sdk/src/driver/falkordb.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/driver/falkordb.ts +// @graph-kit/sdk/src/driver/falkordb.ts // FalkorDB driver adapter - FalkorDB is Redis-based graph database // Uses Redis Stack / RedisGraph protocol (Redis modules) diff --git a/packages/sdk/src/driver/index.ts b/packages/sdk/src/driver/index.ts index f450019..5df5004 100644 --- a/packages/sdk/src/driver/index.ts +++ b/packages/sdk/src/driver/index.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/driver/index.ts +// @graph-kit/sdk/src/driver/index.ts // Driver adapter abstraction for multi-database support (types only - implementations in separate packages) import { raiseGraphError } from '../errors'; diff --git a/packages/sdk/src/driver/kuzu.ts b/packages/sdk/src/driver/kuzu.ts index da73475..b40cc56 100644 --- a/packages/sdk/src/driver/kuzu.ts +++ b/packages/sdk/src/driver/kuzu.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/driver/kuzu.ts +// @graph-kit/sdk/src/driver/kuzu.ts // Kuzu driver adapter - Kuzu is an embedded graph database, used through the `kuzu` npm package import { diff --git a/packages/sdk/src/driver/memgraph.ts b/packages/sdk/src/driver/memgraph.ts index 9f5bae8..164709e 100644 --- a/packages/sdk/src/driver/memgraph.ts +++ b/packages/sdk/src/driver/memgraph.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/driver/memgraph.ts +// @graph-kit/sdk/src/driver/memgraph.ts // Memgraph driver adapter - Memgraph is compatible with Neo4j Bolt protocol // Can use neo4j-driver with some adjustments diff --git a/packages/sdk/src/driver/neo4j.ts b/packages/sdk/src/driver/neo4j.ts index 0fa5538..b389608 100644 --- a/packages/sdk/src/driver/neo4j.ts +++ b/packages/sdk/src/driver/neo4j.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/driver/neo4j.ts +// @graph-kit/sdk/src/driver/neo4j.ts // Neo4j driver adapter - wraps neo4j-driver with connection management import neo4j, { diff --git a/packages/sdk/src/errors/index.ts b/packages/sdk/src/errors/index.ts index 203f2cf..fde153b 100644 --- a/packages/sdk/src/errors/index.ts +++ b/packages/sdk/src/errors/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/errors/index.ts -// Typed graph-om errors. Built on @frontal-labs/error (bundled into the SDK). +// @graph-kit/sdk/src/errors/index.ts +// Typed graph-kit errors. Built on @frontal-labs/error (bundled into the SDK). // // Codes are stable identifiers callers can branch on with `hasCode`. // Messages are developer-facing; surfaces that face clients (MCP, GraphQL) @@ -46,11 +46,11 @@ export interface GraphErrorOptions extends CreateErrorOptions { readonly retry?: RetryPolicy; } -const DOCS_URL = 'https://github.com/frontal-labs/graph-om/blob/main/docs/errors.md'; +const DOCS_URL = 'https://github.com/frontal-labs/graph-kit/blob/main/docs/errors.md'; /** - * A graph-om error. Sets its own `scope` and a docs `link` derived from `code`. - * `retry` is graph-om's own field, set by the thrower; `@frontal-labs/error@0.7.0` + * A graph-kit error. Sets its own `scope` and a docs `link` derived from `code`. + * `retry` is graph-kit's own field, set by the thrower; `@frontal-labs/error@0.7.0` * has no retry option of its own. */ export class GraphError extends FrontalError { @@ -60,14 +60,14 @@ export class GraphError extends FrontalError { const { retry, ...rest } = options; super(message, { ...rest, - scope: 'graph-om', + scope: 'graph-kit', link: rest.link ?? (rest.code ? `${DOCS_URL}#${rest.code}` : undefined), }); this.retry = retry ?? { retryable: false }; } } -/** Create and throw a graph-om error. Declared `never` so callers keep type narrowing. */ +/** Create and throw a graph-kit error. Declared `never` so callers keep type narrowing. */ export function raiseGraphError(message: string, options: GraphErrorOptions): never { throw new GraphError(message, options); } @@ -75,7 +75,7 @@ export function raiseGraphError(message: string, options: GraphErrorOptions): ne export { FrontalError, getRootCause, isFrontalError }; /** - * True when `error` is a graph-om error with one of `codes`. Narrows to `GraphError`, + * True when `error` is a graph-kit error with one of `codes`. Narrows to `GraphError`, * so `statusCode`, `retry` and `metadata` stay typed after the check. */ export function hasCode( @@ -112,7 +112,7 @@ export function connectionFailure( } /** - * Adapter boundary helper: errors that are already graph-om errors pass through + * Adapter boundary helper: errors that are already graph-kit errors pass through * unchanged, and everything else is classified as a driver failure. */ export function classifyDriverError(error: unknown, driver: string): unknown { @@ -120,7 +120,7 @@ export function classifyDriverError(error: unknown, driver: string): unknown { } /** - * Convert a native driver error into a typed graph-om error. + * Convert a native driver error into a typed graph-kit error. * The original error is kept as `cause`, and the driver's own code goes in * `metadata.driverCode`. Driver messages are kept as-is; Cypher text and * parameters are never copied into the error. @@ -157,7 +157,7 @@ export function mapDriverError(error: unknown, context: { driver: string }): Gra } /** - * True when a graph-om error says it is safe to retry. Tag-based, so it works across + * True when a graph-kit error says it is safe to retry. Tag-based, so it works across * package entry points, where `instanceof GraphError` can be false. */ export function isRetryable(error: unknown): boolean { @@ -181,7 +181,7 @@ export function driverErrorBoundary(driver: string) { }; } -/** The stable graph-om code of an error, or undefined for anything else. Safe for metric labels. */ +/** The stable graph-kit code of an error, or undefined for anything else. Safe for metric labels. */ export function errorCode(error: unknown): GraphErrorCode | undefined { return isFrontalError(error) ? (error.code as GraphErrorCode | undefined) : undefined; } @@ -215,7 +215,7 @@ export function toPublic(error: unknown): FrontalError { const statusCode = status !== undefined && status >= 400 && status <= 599 ? status : 500; const message = (code && PUBLIC_MESSAGES[code]) || FALLBACK_PUBLIC_MESSAGE; return new FrontalError(message, { - scope: 'graph-om', + scope: 'graph-kit', code, statusCode, cause: error, diff --git a/packages/sdk/src/graphql/index.ts b/packages/sdk/src/graphql/index.ts index 3f85d02..7e5603b 100644 --- a/packages/sdk/src/graphql/index.ts +++ b/packages/sdk/src/graphql/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/graphql/index.ts -// GraphQL layer for Graph-OM - generates GraphQL schema from Graph-OM schema +// @graph-kit/sdk/src/graphql/index.ts +// GraphQL layer for Graph-Kit - generates GraphQL schema from Graph-Kit schema import { errorResponse, raiseGraphError, toPublic } from '../errors'; import type { GraphSchemaRegistry, NodeConfig, PropertyConfig } from '../types'; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 79cb9bf..35f1c33 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/index.ts -// Graph-OM - Prisma-like DX for graph databases +// @graph-kit/sdk/src/index.ts +// Graph-Kit - Prisma-like DX for graph databases export { type AuthConfig, diff --git a/packages/sdk/src/migration/index.ts b/packages/sdk/src/migration/index.ts index 39f53af..7a8d75b 100644 --- a/packages/sdk/src/migration/index.ts +++ b/packages/sdk/src/migration/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/migration/index.ts -// Migration system for Graph-OM - schema versioning and database migrations +// @graph-kit/sdk/src/migration/index.ts +// Migration system for Graph-Kit - schema versioning and database migrations import { raiseGraphError } from '../errors'; import { QueryCompiler } from '../query'; @@ -52,7 +52,7 @@ export class MigrationRunner { this.driver = options.driver; this.compiler = new QueryCompiler(); this.migrationsDir = options.migrationsDir ?? './migrations'; - this.tableName = options.tableName ?? '_graph_om_migrations'; + this.tableName = options.tableName ?? '_graph_kit_migrations'; this.schema = options.schema; } @@ -229,8 +229,8 @@ export function createMigrationTemplate(options: CreateMigrationOptions): string // Version: ${version} // Created: ${new Date().toISOString()} -import { QueryCompiler } from '@graph-om/sdk/query'; -import type { Migration } from '@graph-om/sdk/migration'; +import { QueryCompiler } from '@graph-kit/sdk/query'; +import type { Migration } from '@graph-kit/sdk/migration'; export const migration: Migration = { version: '${version}', diff --git a/packages/sdk/src/observability/index.ts b/packages/sdk/src/observability/index.ts index 23fcad4..771e600 100644 --- a/packages/sdk/src/observability/index.ts +++ b/packages/sdk/src/observability/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/observability/index.ts -// Query logging, profiling, and observability for Graph-OM +// @graph-kit/sdk/src/observability/index.ts +// Query logging, profiling, and observability for Graph-Kit import { errorCode } from '../errors'; import type { DriverAdapter, QueryResult, TransactionContext } from '../types'; diff --git a/packages/sdk/src/otel/index.ts b/packages/sdk/src/otel/index.ts index b8da4e6..4fb4d8e 100644 --- a/packages/sdk/src/otel/index.ts +++ b/packages/sdk/src/otel/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/otel/index.ts -// OpenTelemetry integration for Graph-OM +// @graph-kit/sdk/src/otel/index.ts +// OpenTelemetry integration for Graph-Kit import { errorCode, isFrontalError } from '../errors'; import type { MetricsCollector } from '../observability'; @@ -174,7 +174,7 @@ let globalTracer: Tracer = new NoopTracer(); let globalMeter: Meter = new NoopMeter(); let isInitialized = false; -/** Tag a span with the graph-om error code and HTTP-style status, when the error has them. */ +/** Tag a span with the graph-kit error code and HTTP-style status, when the error has them. */ function setErrorCode(span: Span, error: unknown): void { const code = errorCode(error); if (code === undefined) return; diff --git a/packages/sdk/src/query/index.ts b/packages/sdk/src/query/index.ts index 4256ba1..33ed06b 100644 --- a/packages/sdk/src/query/index.ts +++ b/packages/sdk/src/query/index.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/query/index.ts +// @graph-kit/sdk/src/query/index.ts // Cypher query compiler - translates high-level queries to optimized Cypher import { raiseGraphError } from '../errors'; diff --git a/packages/sdk/src/schema/index.ts b/packages/sdk/src/schema/index.ts index 4e2f1e8..9a49735 100644 --- a/packages/sdk/src/schema/index.ts +++ b/packages/sdk/src/schema/index.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/schema/index.ts +// @graph-kit/sdk/src/schema/index.ts // Schema definition API - Drizzle-style fluent API import type { diff --git a/packages/sdk/src/schema/parser.ts b/packages/sdk/src/schema/parser.ts index 7f86511..04c32ab 100644 --- a/packages/sdk/src/schema/parser.ts +++ b/packages/sdk/src/schema/parser.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/src/schema/parser.ts +// @graph-kit/sdk/src/schema/parser.ts // AST-based schema parser using TypeScript compiler API import fs from 'node:fs'; diff --git a/packages/sdk/src/seed/index.ts b/packages/sdk/src/seed/index.ts index 8b0e973..c9c1547 100644 --- a/packages/sdk/src/seed/index.ts +++ b/packages/sdk/src/seed/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/seed/index.ts -// Seed/Fixture system for Graph-OM - database seeding and test data generation +// @graph-kit/sdk/src/seed/index.ts +// Seed/Fixture system for Graph-Kit - database seeding and test data generation import { raiseGraphError } from '../errors'; import type { AnyNodeConfig, DriverAdapter, GraphSchemaRegistry } from '../types'; diff --git a/packages/sdk/src/testing/index.ts b/packages/sdk/src/testing/index.ts index c0cd325..0a73a58 100644 --- a/packages/sdk/src/testing/index.ts +++ b/packages/sdk/src/testing/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/testing/index.ts -// Testing utilities for Graph-OM - mock driver, test helpers, fixtures +// @graph-kit/sdk/src/testing/index.ts +// Testing utilities for Graph-Kit - mock driver, test helpers, fixtures import type { DriverCapabilities } from '../driver'; import type { @@ -496,7 +496,7 @@ export function generateTestData(options: GeneratorOptions): T[] { return Array.from({ length: count }, (_, i) => factory(i)); } -// Vitest/Jest matchers for Graph-OM +// Vitest/Jest matchers for Graph-Kit export const graphMatchers = { toBeValidNode(received: unknown, label: string): { pass: boolean; message: () => string } { const pass = diff --git a/packages/sdk/src/types/index.ts b/packages/sdk/src/types/index.ts index 41b66c0..e62d8f2 100644 --- a/packages/sdk/src/types/index.ts +++ b/packages/sdk/src/types/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/types/index.ts -// Core type definitions for Graph-OM +// @graph-kit/sdk/src/types/index.ts +// Core type definitions for Graph-Kit export type PropertyType = | 'string' diff --git a/packages/sdk/src/visualization/index.ts b/packages/sdk/src/visualization/index.ts index 79ba187..25f1f0e 100644 --- a/packages/sdk/src/visualization/index.ts +++ b/packages/sdk/src/visualization/index.ts @@ -1,5 +1,5 @@ -// @graph-om/sdk/src/visualization/index.ts -// Schema visualization and ER diagram generation for Graph-OM +// @graph-kit/sdk/src/visualization/index.ts +// Schema visualization and ER diagram generation for Graph-Kit import { raiseGraphError } from '../errors'; import type { GraphSchemaRegistry, NodeConfig, PropertyConfig, RelationConfig } from '../types'; diff --git a/packages/sdk/tests/config.test.ts b/packages/sdk/tests/config.test.ts index 339c2f1..1721939 100644 --- a/packages/sdk/tests/config.test.ts +++ b/packages/sdk/tests/config.test.ts @@ -55,14 +55,14 @@ describe('loadConfig', () => { expect(config).toBeNull(); }); - it('loads graph-om.config.json', async () => { + it('loads graph-kit.config.json', async () => { const fs = await import('node:fs'); const os = await import('node:os'); const path = await import('node:path'); - const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-om-config-')); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'graph-kit-config-')); try { fs.writeFileSync( - path.join(dir, 'graph-om.config.json'), + path.join(dir, 'graph-kit.config.json'), JSON.stringify({ schema: './my-schema.ts', debug: true }), ); const config = await loadConfig(dir); diff --git a/packages/sdk/tests/driver-falkordb.test.ts b/packages/sdk/tests/driver-falkordb.test.ts index f6a48e4..aa6d49f 100644 --- a/packages/sdk/tests/driver-falkordb.test.ts +++ b/packages/sdk/tests/driver-falkordb.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/driver-falkordb.test.ts +// @graph-kit/sdk/tests/driver-falkordb.test.ts // The FalkorDB adapter talks Redis through `ioredis`, so these tests replace it with a fake // that records every command. import { beforeEach, describe, expect, it, vi } from 'vitest'; diff --git a/packages/sdk/tests/driver-kuzu.test.ts b/packages/sdk/tests/driver-kuzu.test.ts index 4af770e..df43942 100644 --- a/packages/sdk/tests/driver-kuzu.test.ts +++ b/packages/sdk/tests/driver-kuzu.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/driver-kuzu.test.ts +// @graph-kit/sdk/tests/driver-kuzu.test.ts // Kuzu is an embedded database loaded at runtime. These tests replace the `kuzu` module with an // in-memory fake that records every statement, so the adapter's own logic is what gets tested. import { beforeEach, describe, expect, it, vi } from 'vitest'; diff --git a/packages/sdk/tests/driver-memgraph.test.ts b/packages/sdk/tests/driver-memgraph.test.ts index c5d0c8c..f3f9998 100644 --- a/packages/sdk/tests/driver-memgraph.test.ts +++ b/packages/sdk/tests/driver-memgraph.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/driver-memgraph.test.ts +// @graph-kit/sdk/tests/driver-memgraph.test.ts // The Memgraph adapter speaks Bolt through the Neo4j adapter, so these tests replace that // adapter with a stub and check what Memgraph passes through and how it translates settings. import { beforeEach, describe, expect, it, vi } from 'vitest'; diff --git a/packages/sdk/tests/driver-neo4j.test.ts b/packages/sdk/tests/driver-neo4j.test.ts index 6d9ca89..803f6a8 100644 --- a/packages/sdk/tests/driver-neo4j.test.ts +++ b/packages/sdk/tests/driver-neo4j.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/driver-neo4j.test.ts +// @graph-kit/sdk/tests/driver-neo4j.test.ts import neo4j from 'neo4j-driver'; import { beforeEach, describe, expect, it, type Mock, vi } from 'vitest'; @@ -362,11 +362,11 @@ describe('Neo4jDriverAdapter error classification', () => { ).rejects.toBe(userError); }); - it('passes a graph-om error from the user callback through unchanged', async () => { + it('passes a graph-kit error from the user callback through unchanged', async () => { session().executeWrite.mockImplementationOnce( async (work: (txc: unknown) => Promise) => work({ run: vi.fn() }), ); - const { GraphError } = await import('@graph-om/sdk/errors'); + const { GraphError } = await import('@graph-kit/sdk/errors'); const own = new GraphError('own', { code: 'invalid_argument', statusCode: 400 }); await expect( diff --git a/packages/sdk/tests/driver-registry.test.ts b/packages/sdk/tests/driver-registry.test.ts index cc00491..faf2bb0 100644 --- a/packages/sdk/tests/driver-registry.test.ts +++ b/packages/sdk/tests/driver-registry.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/driver-registry.test.ts +// @graph-kit/sdk/tests/driver-registry.test.ts import { describe, expect, it } from 'vitest'; import { FalkorDBDriverAdapter } from '../src/driver/falkordb'; import { createDriver, listDrivers } from '../src/driver/index'; diff --git a/packages/sdk/tests/error-surfaces.test.ts b/packages/sdk/tests/error-surfaces.test.ts index 6fba4d3..340e47a 100644 --- a/packages/sdk/tests/error-surfaces.test.ts +++ b/packages/sdk/tests/error-surfaces.test.ts @@ -27,7 +27,7 @@ describe('client-facing error payloads', () => { expect(status).toBe(404); expect(Object.keys(data.error).sort()).toEqual(['code', 'message', 'scope']); expect(data.error).toEqual({ - scope: 'graph-om', + scope: 'graph-kit', code: 'record_not_found', message: 'The requested record does not exist', }); @@ -78,7 +78,7 @@ describe('GraphQL resolver errors', () => { expect(error.message).toBe('The requested record does not exist'); expect(error.extensions).toEqual({ - scope: 'graph-om', + scope: 'graph-kit', code: 'record_not_found', message: 'The requested record does not exist', }); diff --git a/packages/sdk/tests/errors.test.ts b/packages/sdk/tests/errors.test.ts index 0efafcc..ac701f1 100644 --- a/packages/sdk/tests/errors.test.ts +++ b/packages/sdk/tests/errors.test.ts @@ -18,7 +18,7 @@ function driverError(code: string | undefined, message = 'driver said no'): Erro return error; } -describe('graph-om errors', () => { +describe('graph-kit errors', () => { it('creates scoped, tagged errors that still extend Error', () => { const error = new GraphError('boom', { code: 'query_failed', statusCode: 500 }); @@ -26,7 +26,7 @@ describe('graph-om errors', () => { expect(error).toBeInstanceOf(FrontalError); expect(error).toBeInstanceOf(Error); expect(isFrontalError(error)).toBe(true); - expect(error.scope).toBe('graph-om'); + expect(error.scope).toBe('graph-kit'); expect(error.message).toBe('boom'); }); @@ -34,7 +34,7 @@ describe('graph-om errors', () => { expect(new GraphError('x', { code: 'query_failed' }).retry).toEqual({ retryable: false }); }); - it('keeps retry as graph-om metadata, not as a frontal option', () => { + it('keeps retry as graph-kit metadata, not as a frontal option', () => { const error = new GraphError('x', { code: 'connection_failed', retry: { retryable: true }, @@ -45,7 +45,7 @@ describe('graph-om errors', () => { it('links each code to its anchor in the errors doc', () => { const error = new GraphError('x', { code: 'record_not_found' }); expect(error.link).toBe( - 'https://github.com/frontal-labs/graph-om/blob/main/docs/errors.md#record_not_found', + 'https://github.com/frontal-labs/graph-kit/blob/main/docs/errors.md#record_not_found', ); }); @@ -177,7 +177,7 @@ describe('mapDriverError', () => { }); describe('classifyDriverError', () => { - it('passes graph-om errors through unchanged', () => { + it('passes graph-kit errors through unchanged', () => { const original = new GraphError('x', { code: 'record_not_found' }); expect(classifyDriverError(original, 'neo4j')).toBe(original); }); diff --git a/packages/sdk/tests/integration-falkordb.test.ts b/packages/sdk/tests/integration-falkordb.test.ts index 150949a..a3dca81 100644 --- a/packages/sdk/tests/integration-falkordb.test.ts +++ b/packages/sdk/tests/integration-falkordb.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/integration-falkordb.test.ts +// @graph-kit/sdk/tests/integration-falkordb.test.ts // Runs against a live FalkorDB. Set FALKORDB_URI (for example redis://127.0.0.1:6380). import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { createFalkorDBDriver } from '../src/driver/falkordb'; diff --git a/packages/sdk/tests/integration-kuzu.test.ts b/packages/sdk/tests/integration-kuzu.test.ts index 0b8cd21..fade0a7 100644 --- a/packages/sdk/tests/integration-kuzu.test.ts +++ b/packages/sdk/tests/integration-kuzu.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/integration-kuzu.test.ts +// @graph-kit/sdk/tests/integration-kuzu.test.ts // Runs against the real `kuzu` package on a throwaway database. Kuzu is embedded, so no server. import { mkdtempSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; @@ -7,7 +7,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { createKuzuDriverAsync } from '../src/driver/index'; describe('Kuzu integration', () => { - const dir = mkdtempSync(path.join(tmpdir(), 'graph-om-kuzu-')); + const dir = mkdtempSync(path.join(tmpdir(), 'graph-kit-kuzu-')); const databasePath = path.join(dir, 'graph.kuzu'); let driver: Awaited>; diff --git a/packages/sdk/tests/integration-memgraph.test.ts b/packages/sdk/tests/integration-memgraph.test.ts index 4ddcc0f..b5b9670 100644 --- a/packages/sdk/tests/integration-memgraph.test.ts +++ b/packages/sdk/tests/integration-memgraph.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/integration-memgraph.test.ts +// @graph-kit/sdk/tests/integration-memgraph.test.ts // Runs against a live Memgraph over Bolt. Set MEMGRAPH_URI (for example bolt://127.0.0.1:7688). import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { createMemgraphDriver } from '../src/driver/memgraph'; diff --git a/packages/sdk/tests/integration.test.ts b/packages/sdk/tests/integration.test.ts index 2ac04a0..b5fd1e3 100644 --- a/packages/sdk/tests/integration.test.ts +++ b/packages/sdk/tests/integration.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/integration.test.ts +// @graph-kit/sdk/tests/integration.test.ts // Opt-in integration tests against a live Neo4j instance. // Run: docker compose up -d && NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j NEO4J_PASSWORD=password pnpm test import { afterAll, beforeAll, describe, expect, it } from 'vitest'; diff --git a/packages/sdk/tests/schema-builder.test.ts b/packages/sdk/tests/schema-builder.test.ts index 0bf8e4e..71809c9 100644 --- a/packages/sdk/tests/schema-builder.test.ts +++ b/packages/sdk/tests/schema-builder.test.ts @@ -1,4 +1,4 @@ -// @graph-om/sdk/tests/schema-builder.test.ts +// @graph-kit/sdk/tests/schema-builder.test.ts import { describe, expect, it } from 'vitest'; import { date, diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index 14462b7..9a9da56 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@graph-om/sdk/*": ["./src/*"] + "@graph-kit/sdk/*": ["./src/*"] }, "outDir": "./dist", "rootDir": "./src", diff --git a/packages/sdk/tsup.config.ts b/packages/sdk/tsup.config.ts index b019440..39d2a2c 100644 --- a/packages/sdk/tsup.config.ts +++ b/packages/sdk/tsup.config.ts @@ -34,6 +34,6 @@ export default defineConfig({ // @frontal-labs/error is ESM-only; bundle it so the CJS build keeps working. noExternal: ['@frontal-labs/error'], banner: { - js: '// @graph-om/sdk - Prisma-like DX for graph databases', + js: '// @graph-kit/sdk - Prisma-like DX for graph databases', }, }); diff --git a/packages/testing/README.md b/packages/testing/README.md index 327baea..201ada5 100644 --- a/packages/testing/README.md +++ b/packages/testing/README.md @@ -1,18 +1,18 @@ -# @graph-om/testing +# @graph-kit/testing -Graph-OM testing utilities — mock driver, test helpers, matchers, and fixtures for unit testing Graph-OM applications without a live graph database. +Graph-Kit testing utilities — mock driver, test helpers, matchers, and fixtures for unit testing Graph-Kit applications without a live graph database. ## Installation ```bash -pnpm add -D @graph-om/testing @graph-om/sdk +pnpm add -D @graph-kit/testing @graph-kit/sdk ``` ## Quick start ```ts -import { createMockDriver, graphMatchers, generateTestData } from '@graph-om/testing'; -import { GraphClient } from '@graph-om/sdk'; +import { createMockDriver, graphMatchers, generateTestData } from '@graph-kit/testing'; +import { GraphClient } from '@graph-kit/sdk'; const mock = createMockDriver(); const client = new GraphClient(mock, graph); @@ -59,7 +59,7 @@ Vitest/Jest-style matchers: Usage: ```ts -import { graphMatchers } from '@graph-om/testing'; +import { graphMatchers } from '@graph-kit/testing'; // extend expect or call directly expect(graphMatchers.toBeValidNode(node, 'User').pass).toBe(true); ``` @@ -81,7 +81,7 @@ expect(graphMatchers.toBeValidNode(node, 'User').pass).toBe(true); ## Re-exported types -The package re-exports core types from `@graph-om/sdk`: `DriverAdapter`, `DriverCapabilities`, `GraphConfig`, `GraphSchemaRegistry`, `NodeConfig`, `PropertyConfig`, `QueryRecord`, `QueryResult`, `RelationConfig`, `TransactionContext`, `WhereCondition`. +The package re-exports core types from `@graph-kit/sdk`: `DriverAdapter`, `DriverCapabilities`, `GraphConfig`, `GraphSchemaRegistry`, `NodeConfig`, `PropertyConfig`, `QueryRecord`, `QueryResult`, `RelationConfig`, `TransactionContext`, `WhereCondition`. ## License diff --git a/packages/testing/package.json b/packages/testing/package.json index 26f7fb5..4b304a5 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -1,22 +1,22 @@ { - "name": "@graph-om/testing", + "name": "@graph-kit/testing", "version": "0.0.1", - "description": "Graph-OM testing utilities - mock driver, test helpers, fixtures", + "description": "Graph-Kit testing utilities - mock driver, test helpers, fixtures", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git", + "url": "https://github.com/frontal-labs/graph-kit.git", "directory": "packages/testing" }, - "homepage": "https://github.com/frontal-labs/graph-om/tree/master/packages/testing#readme", + "homepage": "https://github.com/frontal-labs/graph-kit/tree/master/packages/testing#readme", "bugs": { - "url": "https://github.com/frontal-labs/graph-om/issues" + "url": "https://github.com/frontal-labs/graph-kit/issues" }, "keywords": [ "testing", "mock", "fixtures", - "graph-om" + "graph-kit" ], "sideEffects": false, "files": [ @@ -44,7 +44,7 @@ }, "dependencies": {}, "devDependencies": { - "@graph-om/sdk": "workspace:*", + "@graph-kit/sdk": "workspace:*", "@types/node": "^20.10.0", "tsup": "^8.0.0", "typescript": "^5.9.3", diff --git a/packages/testing/src/driver/index.ts b/packages/testing/src/driver/index.ts index 27088c4..0c6d5f2 100644 --- a/packages/testing/src/driver/index.ts +++ b/packages/testing/src/driver/index.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/driver/index.ts +// @graph-kit/testing/src/driver/index.ts // Mock driver domain barrel export { createMockDriver, MockDriverAdapter } from './mock-driver'; diff --git a/packages/testing/src/driver/mock-driver.ts b/packages/testing/src/driver/mock-driver.ts index a877357..62fa405 100644 --- a/packages/testing/src/driver/mock-driver.ts +++ b/packages/testing/src/driver/mock-driver.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/driver/mock-driver.ts +// @graph-kit/testing/src/driver/mock-driver.ts // Mock DriverAdapter implementation for testing without a live database import type { @@ -7,7 +7,7 @@ import type { QueryRecord, QueryResult, TransactionContext, -} from '@graph-om/sdk'; +} from '@graph-kit/sdk'; export class MockDriverAdapter implements DriverAdapter { private data: Map>> = new Map(); diff --git a/packages/testing/src/fixtures/index.ts b/packages/testing/src/fixtures/index.ts index 25b6c8b..274d9aa 100644 --- a/packages/testing/src/fixtures/index.ts +++ b/packages/testing/src/fixtures/index.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/fixtures/index.ts +// @graph-kit/testing/src/fixtures/index.ts // Fixtures domain barrel export type { TestFixture } from './test-fixtures'; diff --git a/packages/testing/src/fixtures/test-fixtures.ts b/packages/testing/src/fixtures/test-fixtures.ts index 2ed6b36..6c68428 100644 --- a/packages/testing/src/fixtures/test-fixtures.ts +++ b/packages/testing/src/fixtures/test-fixtures.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/fixtures/test-fixtures.ts +// @graph-kit/testing/src/fixtures/test-fixtures.ts // Test fixtures and data generation helpers export interface TestFixture { diff --git a/packages/testing/src/generators/index.ts b/packages/testing/src/generators/index.ts index 9477eef..d1ca4df 100644 --- a/packages/testing/src/generators/index.ts +++ b/packages/testing/src/generators/index.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/generators/index.ts +// @graph-kit/testing/src/generators/index.ts // Generators domain barrel export { diff --git a/packages/testing/src/generators/random.ts b/packages/testing/src/generators/random.ts index e8fc82f..1561306 100644 --- a/packages/testing/src/generators/random.ts +++ b/packages/testing/src/generators/random.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/generators/random.ts +// @graph-kit/testing/src/generators/random.ts // Random data generators for test data export function generateRandomString(length = 10): string { diff --git a/packages/testing/src/index.ts b/packages/testing/src/index.ts index 6b6137c..75958c2 100644 --- a/packages/testing/src/index.ts +++ b/packages/testing/src/index.ts @@ -1,8 +1,8 @@ -// @graph-om/testing/src/index.ts -// Testing utilities for Graph-OM - mock driver, test helpers, fixtures +// @graph-kit/testing/src/index.ts +// Testing utilities for Graph-Kit - mock driver, test helpers, fixtures // Barrel export - manually selects and re-exports public API -// Type re-exports from @graph-om/sdk +// Type re-exports from @graph-kit/sdk export type { DriverAdapter, DriverCapabilities, @@ -15,7 +15,7 @@ export type { RelationConfig, TransactionContext, WhereCondition, -} from '@graph-om/sdk'; +} from '@graph-kit/sdk'; // Driver domain export { createMockDriver, MockDriverAdapter } from './driver/index'; diff --git a/packages/testing/src/matchers/graph-matchers.ts b/packages/testing/src/matchers/graph-matchers.ts index 4257830..2ca5055 100644 --- a/packages/testing/src/matchers/graph-matchers.ts +++ b/packages/testing/src/matchers/graph-matchers.ts @@ -1,5 +1,5 @@ -// @graph-om/testing/src/matchers/graph-matchers.ts -// Vitest/Jest matchers for Graph-OM +// @graph-kit/testing/src/matchers/graph-matchers.ts +// Vitest/Jest matchers for Graph-Kit type MatchableNode = { label?: unknown; relations?: Record } | null | undefined; diff --git a/packages/testing/src/matchers/index.ts b/packages/testing/src/matchers/index.ts index de60cc1..6dd1275 100644 --- a/packages/testing/src/matchers/index.ts +++ b/packages/testing/src/matchers/index.ts @@ -1,4 +1,4 @@ -// @graph-om/testing/src/matchers/index.ts +// @graph-kit/testing/src/matchers/index.ts // Matchers domain barrel export { graphMatchers } from './graph-matchers'; diff --git a/packages/testing/tsup.config.ts b/packages/testing/tsup.config.ts index 3b0d98a..02128d4 100644 --- a/packages/testing/tsup.config.ts +++ b/packages/testing/tsup.config.ts @@ -8,8 +8,8 @@ export default defineConfig({ sourcemap: true, clean: true, treeshake: true, - external: ['@graph-om/sdk'], + external: ['@graph-kit/sdk'], banner: { - js: '// @graph-om/testing - Testing utilities for Graph-OM', + js: '// @graph-kit/testing - Testing utilities for Graph-Kit', }, }); diff --git a/packages/zod/README.md b/packages/zod/README.md index e8c0b20..72a6088 100644 --- a/packages/zod/README.md +++ b/packages/zod/README.md @@ -1,23 +1,23 @@ -# @graph-om/zod +# @graph-kit/zod -Zod validation integration for Graph-OM. Converts `NodeConfig` objects into Zod schemas and provides create/update validators and validation hooks for type-safe graph node input. +Zod validation integration for Graph-Kit. Converts `NodeConfig` objects into Zod schemas and provides create/update validators and validation hooks for type-safe graph node input. ## Installation ```bash -pnpm add @graph-om/zod zod +pnpm add @graph-kit/zod zod ``` -`@graph-om/sdk` is a peer dependency — install it alongside: +`@graph-kit/sdk` is a peer dependency — install it alongside: ```bash -pnpm add @graph-om/sdk +pnpm add @graph-kit/sdk ``` ## Quick start ```ts -import { toZodSchema, toCreateSchema, toUpdateSchema, validateCreate, validateUpdate, validationHooks } from '@graph-om/zod'; +import { toZodSchema, toCreateSchema, toUpdateSchema, validateCreate, validateUpdate, validationHooks } from '@graph-kit/zod'; import { User } from './schema.js'; const schema = toZodSchema(User); @@ -60,7 +60,7 @@ Modifiers: ## Peer dependency -`@graph-om/sdk` (`workspace:^`) provides the `NodeConfig`, `PropertyConfig`, `PropertyType`, `CreateInput`, and `UpdateInput` types used by this package. +`@graph-kit/sdk` (`workspace:^`) provides the `NodeConfig`, `PropertyConfig`, `PropertyType`, `CreateInput`, and `UpdateInput` types used by this package. ## License diff --git a/packages/zod/package.json b/packages/zod/package.json index 1e624e8..a7de4a3 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -1,23 +1,23 @@ { - "name": "@graph-om/zod", + "name": "@graph-kit/zod", "version": "0.0.1", - "description": "Zod validation integration for Graph-OM", + "description": "Zod validation integration for Graph-Kit", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/frontal-labs/graph-om.git", + "url": "https://github.com/frontal-labs/graph-kit.git", "directory": "packages/zod" }, - "homepage": "https://github.com/frontal-labs/graph-om/tree/master/packages/zod#readme", + "homepage": "https://github.com/frontal-labs/graph-kit/tree/master/packages/zod#readme", "bugs": { - "url": "https://github.com/frontal-labs/graph-om/issues" + "url": "https://github.com/frontal-labs/graph-kit/issues" }, "keywords": [ "zod", "validation", "ogm", "neo4j", - "graph-om" + "graph-kit" ], "sideEffects": false, "files": [ @@ -47,10 +47,10 @@ "zod": "^4.6.7" }, "peerDependencies": { - "@graph-om/sdk": "workspace:^" + "@graph-kit/sdk": "workspace:^" }, "devDependencies": { - "@graph-om/sdk": "workspace:*", + "@graph-kit/sdk": "workspace:*", "@types/node": "^20.10.0", "tsup": "^8.0.0", "typescript": "^5.9.3", diff --git a/packages/zod/src/index.ts b/packages/zod/src/index.ts index 75dd27d..d7b479f 100644 --- a/packages/zod/src/index.ts +++ b/packages/zod/src/index.ts @@ -1,5 +1,5 @@ -// @graph-om/zod/src/index.ts -// Zod validation integration for Graph-OM +// @graph-kit/zod/src/index.ts +// Zod validation integration for Graph-Kit // Barrel export - manually selects and re-exports public API // Schema generation domain diff --git a/packages/zod/src/schema/factory.ts b/packages/zod/src/schema/factory.ts index a2cb57f..4c142ad 100644 --- a/packages/zod/src/schema/factory.ts +++ b/packages/zod/src/schema/factory.ts @@ -1,7 +1,7 @@ -// @graph-om/zod/src/schema/factory.ts +// @graph-kit/zod/src/schema/factory.ts // Zod schema factory functions for node configs -import type { NodeConfig, PropertyConfig, PropertyType } from '@graph-om/sdk'; +import type { NodeConfig, PropertyConfig, PropertyType } from '@graph-kit/sdk'; import { z } from 'zod'; import { propertiesToZodShape, propertyTypeToZod } from './property'; diff --git a/packages/zod/src/schema/index.ts b/packages/zod/src/schema/index.ts index a561eb8..11018cf 100644 --- a/packages/zod/src/schema/index.ts +++ b/packages/zod/src/schema/index.ts @@ -1,4 +1,4 @@ -// @graph-om/zod/src/schema/index.ts +// @graph-kit/zod/src/schema/index.ts // Schema generation domain barrel export { toCreateSchema, toUpdateSchema, toZodSchema } from './factory'; diff --git a/packages/zod/src/schema/property.ts b/packages/zod/src/schema/property.ts index 01f6060..44321a0 100644 --- a/packages/zod/src/schema/property.ts +++ b/packages/zod/src/schema/property.ts @@ -1,7 +1,7 @@ -// @graph-om/zod/src/schema/property.ts +// @graph-kit/zod/src/schema/property.ts // Property-level Zod schema conversion -import type { PropertyConfig, PropertyType } from '@graph-om/sdk'; +import type { PropertyConfig, PropertyType } from '@graph-kit/sdk'; import { z } from 'zod'; import type { PropertyTypeToZodType } from './types'; diff --git a/packages/zod/src/schema/types.ts b/packages/zod/src/schema/types.ts index 34677b2..b365af9 100644 --- a/packages/zod/src/schema/types.ts +++ b/packages/zod/src/schema/types.ts @@ -1,7 +1,7 @@ -// @graph-om/zod/src/schema/types.ts +// @graph-kit/zod/src/schema/types.ts // Type aliases for Zod schema generation -import type { PropertyType } from '@graph-om/sdk'; +import type { PropertyType } from '@graph-kit/sdk'; import type { z } from 'zod'; export type PropertyTypeToZodType = T extends 'string' diff --git a/packages/zod/src/validation/hooks.ts b/packages/zod/src/validation/hooks.ts index ca8a3e9..cb62e5b 100644 --- a/packages/zod/src/validation/hooks.ts +++ b/packages/zod/src/validation/hooks.ts @@ -1,7 +1,7 @@ -// @graph-om/zod/src/validation/hooks.ts +// @graph-kit/zod/src/validation/hooks.ts // Validation hooks for create and update lifecycle events -import type { CreateInput, NodeConfig, PropertyConfig, UpdateInput } from '@graph-om/sdk'; +import type { CreateInput, NodeConfig, PropertyConfig, UpdateInput } from '@graph-kit/sdk'; import { validateCreate, validateUpdate } from './validate'; export function validationHooks( diff --git a/packages/zod/src/validation/index.ts b/packages/zod/src/validation/index.ts index dec2920..72d5fd0 100644 --- a/packages/zod/src/validation/index.ts +++ b/packages/zod/src/validation/index.ts @@ -1,4 +1,4 @@ -// @graph-om/zod/src/validation/index.ts +// @graph-kit/zod/src/validation/index.ts // Validation domain barrel export { validationHooks } from './hooks'; diff --git a/packages/zod/src/validation/validate.ts b/packages/zod/src/validation/validate.ts index b4877f1..4cf22a0 100644 --- a/packages/zod/src/validation/validate.ts +++ b/packages/zod/src/validation/validate.ts @@ -1,7 +1,7 @@ -// @graph-om/zod/src/validation/validate.ts +// @graph-kit/zod/src/validation/validate.ts // Validation functions for create and update operations -import type { CreateInput, NodeConfig, PropertyConfig, UpdateInput } from '@graph-om/sdk'; +import type { CreateInput, NodeConfig, PropertyConfig, UpdateInput } from '@graph-kit/sdk'; import type { z } from 'zod'; import { toCreateSchema, toUpdateSchema } from '../schema/factory'; diff --git a/packages/zod/tsup.config.ts b/packages/zod/tsup.config.ts index 59db98e..72487e2 100644 --- a/packages/zod/tsup.config.ts +++ b/packages/zod/tsup.config.ts @@ -8,8 +8,8 @@ export default defineConfig({ sourcemap: true, clean: true, treeshake: true, - external: ['zod', '@graph-om/sdk'], + external: ['zod', '@graph-kit/sdk'], banner: { - js: '// @graph-om/zod - Zod validation integration for Graph-OM', + js: '// @graph-kit/zod - Zod validation integration for Graph-Kit', }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f88c3bd..9a4e996 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,12 +64,465 @@ importers: specifier: ^4.6.7 version: 4.6.7 + examples/aggregations: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/bulk-operations: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/configuration: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/crud-operations: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/error-handling: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/graphql-schema: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@apollo/server': + specifier: ^5.5.1 + version: 5.5.1(graphql@16.15.0) + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/migrations: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/mock-driver-testing: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/multi-driver: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/observability: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/pagination: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/path-traversal: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/query-filters: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/raw-cypher: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/relations: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/schema-definition: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/seeding: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/selective-fields: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + examples/social-graph: dependencies: - '@graph-om/sdk': + '@graph-kit/sdk': specifier: workspace:* version: link:../../packages/sdk - '@graph-om/zod': + '@graph-kit/zod': specifier: workspace:* version: link:../../packages/zod zod: @@ -79,7 +532,63 @@ importers: '@apollo/server': specifier: ^5.5.1 version: 5.5.1(graphql@16.15.0) - '@graph-om/cli': + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/transactions: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + devDependencies: + '@graph-kit/cli': + specifier: workspace:* + version: link:../../packages/cli + '@types/node': + specifier: ^20.0.0 + version: 20.19.43 + tsx: + specifier: ^4.23.15 + version: 4.23.15 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.0.0 + version: 7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1) + vitest: + specifier: ^4.1.12 + version: 4.1.12(@opentelemetry/api@1.10.0)(@types/node@20.19.43)(vite@7.3.7(@types/node@20.19.43)(tsx@4.23.15)(yaml@2.9.1)) + + examples/zod-validation: + dependencies: + '@graph-kit/sdk': + specifier: workspace:* + version: link:../../packages/sdk + '@graph-kit/zod': + specifier: workspace:* + version: link:../../packages/zod + zod: + specifier: ^4.6.7 + version: 4.6.7 + devDependencies: + '@graph-kit/cli': specifier: workspace:* version: link:../../packages/cli '@types/node': @@ -100,7 +609,7 @@ importers: packages/cli: dependencies: - '@graph-om/sdk': + '@graph-kit/sdk': specifier: workspace:* version: link:../sdk commander: @@ -129,7 +638,7 @@ importers: specifier: ^1.32.2 version: 1.32.2(zod@4.6.7) devDependencies: - '@graph-om/sdk': + '@graph-kit/sdk': specifier: workspace:* version: link:../sdk '@types/node': @@ -150,7 +659,7 @@ importers: packages/migrate: devDependencies: - '@graph-om/sdk': + '@graph-kit/sdk': specifier: workspace:* version: link:../sdk '@types/node': @@ -248,7 +757,7 @@ importers: packages/testing: devDependencies: - '@graph-om/sdk': + '@graph-kit/sdk': specifier: workspace:* version: link:../sdk '@types/node': @@ -273,7 +782,7 @@ importers: specifier: ^4.6.7 version: 4.6.7 devDependencies: - '@graph-om/sdk': + '@graph-kit/sdk': specifier: workspace:* version: link:../sdk '@types/node': diff --git a/tests/bin.test.ts b/tests/bin.test.ts index 6678e35..a4a703f 100644 --- a/tests/bin.test.ts +++ b/tests/bin.test.ts @@ -14,6 +14,6 @@ describe('root bin/index.js', () => { it('shows the CLI help', () => { const out = execFileSync(process.execPath, [launcher, '--help'], { encoding: 'utf8' }); - expect(out).toContain('Usage: graph-om'); + expect(out).toContain('Usage: graph-kit'); }, 30_000); }); diff --git a/tests/cli_template.test.ts b/tests/cli_template.test.ts index 127ccfe..e377753 100644 --- a/tests/cli_template.test.ts +++ b/tests/cli_template.test.ts @@ -1,5 +1,5 @@ -// @graph-om/tests/cli_template.test.ts -// Cross-reference test: validates CLI generated output references @graph-om/sdk env correctly +// @graph-kit/tests/cli_template.test.ts +// Cross-reference test: validates CLI generated output references @graph-kit/sdk env correctly import fs from 'node:fs'; import path from 'node:path'; @@ -8,11 +8,11 @@ import { describe, expect, it } from 'vitest'; describe('CLI generated output cross-references', () => { const cliSrc = path.join(process.cwd(), 'packages/cli/src/commands'); - it('init.ts template imports env from @graph-om/sdk', () => { + it('init.ts template imports env from @graph-kit/sdk', () => { const initContent = fs.readFileSync(path.join(cliSrc, 'init.ts'), 'utf-8'); // The generated src/index.ts template should import env - expect(initContent).toContain("import { GraphClient, env } from '@graph-om/sdk';"); + expect(initContent).toContain("import { GraphClient, env } from '@graph-kit/sdk';"); // Should use env.NEO4J_* not process.env.NEO4J_* expect(initContent).toContain('uri: env.NEO4J_URI'); expect(initContent).toContain('username: env.NEO4J_USER'); @@ -21,11 +21,11 @@ describe('CLI generated output cross-references', () => { expect(initContent).not.toContain("process.env.NEO4J_URI || 'bolt://"); }); - it('generate.ts createClient template imports env from @graph-om/sdk', () => { + it('generate.ts createClient template imports env from @graph-kit/sdk', () => { const generateContent = fs.readFileSync(path.join(cliSrc, 'generate.ts'), 'utf-8'); // The generated client.ts template should import env - expect(generateContent).toContain("import { GraphClient, env } from '@graph-om/sdk';"); + expect(generateContent).toContain("import { GraphClient, env } from '@graph-kit/sdk';"); // Should use env.NEO4J_* as defaults expect(generateContent).toContain('uri: config.uri || env.NEO4J_URI'); expect(generateContent).toContain('username: config.username || env.NEO4J_USER'); @@ -37,7 +37,7 @@ describe('CLI generated output cross-references', () => { fs.readFileSync(path.join(process.cwd(), 'packages/cli/package.json'), 'utf-8'), ); - expect(pkg.name).toBe('@graph-om/cli'); - expect(pkg.bin?.['graph-om']).toBe('./dist/index.mjs'); + expect(pkg.name).toBe('@graph-kit/cli'); + expect(pkg.bin?.['graph-kit']).toBe('./dist/index.mjs'); }); }); diff --git a/tests/env.test.ts b/tests/env.test.ts index 69e6ef6..361d5a9 100644 --- a/tests/env.test.ts +++ b/tests/env.test.ts @@ -1,5 +1,5 @@ -// @graph-om/tests/env.test.ts -// Cross-package test: validates @t3-oss/env-core + zod env schema from @graph-om/sdk +// @graph-kit/tests/env.test.ts +// Cross-package test: validates @t3-oss/env-core + zod env schema from @graph-kit/sdk import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { z } from 'zod'; @@ -15,14 +15,14 @@ afterEach(() => { vi.restoreAllMocks(); }); -describe('@graph-om/sdk env schema', () => { +describe('@graph-kit/sdk env schema', () => { it('applies defaults when env vars are missing', async () => { // Clear Neo4j env vars to test defaults delete process.env.NEO4J_URI; delete process.env.NEO4J_USER; delete process.env.NEO4J_PASSWORD; delete process.env.NEO4J_DATABASE; - delete process.env.GRAPH_OM_DEBUG; + delete process.env.GRAPH_KIT_DEBUG; // Dynamically import to get fresh env instance const { createEnv } = await import('@t3-oss/env-core'); @@ -33,7 +33,7 @@ describe('@graph-om/sdk env schema', () => { NEO4J_USER: z.string().default('neo4j'), NEO4J_PASSWORD: z.string().default('password'), NEO4J_DATABASE: z.string().optional(), - GRAPH_OM_DEBUG: z + GRAPH_KIT_DEBUG: z .string() .optional() .transform((val) => val === 'true'), @@ -46,7 +46,7 @@ describe('@graph-om/sdk env schema', () => { expect(env.NEO4J_USER).toBe('neo4j'); expect(env.NEO4J_PASSWORD).toBe('password'); expect(env.NEO4J_DATABASE).toBeUndefined(); - expect(env.GRAPH_OM_DEBUG).toBe(false); + expect(env.GRAPH_KIT_DEBUG).toBe(false); }); it('reads values from process.env when present', async () => { @@ -54,7 +54,7 @@ describe('@graph-om/sdk env schema', () => { process.env.NEO4J_USER = 'custom-user'; process.env.NEO4J_PASSWORD = 'custom-pass'; process.env.NEO4J_DATABASE = 'custom-db'; - process.env.GRAPH_OM_DEBUG = 'true'; + process.env.GRAPH_KIT_DEBUG = 'true'; const { createEnv } = await import('@t3-oss/env-core'); @@ -64,7 +64,7 @@ describe('@graph-om/sdk env schema', () => { NEO4J_USER: z.string().default('neo4j'), NEO4J_PASSWORD: z.string().default('password'), NEO4J_DATABASE: z.string().optional(), - GRAPH_OM_DEBUG: z + GRAPH_KIT_DEBUG: z .string() .optional() .transform((val) => val === 'true'), @@ -77,17 +77,17 @@ describe('@graph-om/sdk env schema', () => { expect(env.NEO4J_USER).toBe('custom-user'); expect(env.NEO4J_PASSWORD).toBe('custom-pass'); expect(env.NEO4J_DATABASE).toBe('custom-db'); - expect(env.GRAPH_OM_DEBUG).toBe(true); + expect(env.GRAPH_KIT_DEBUG).toBe(true); }); - it('GRAPH_OM_DEBUG=false string becomes boolean false', async () => { - process.env.GRAPH_OM_DEBUG = 'false'; + it('GRAPH_KIT_DEBUG=false string becomes boolean false', async () => { + process.env.GRAPH_KIT_DEBUG = 'false'; const { createEnv } = await import('@t3-oss/env-core'); const env = createEnv({ server: { - GRAPH_OM_DEBUG: z + GRAPH_KIT_DEBUG: z .string() .optional() .transform((val) => val === 'true'), @@ -96,6 +96,6 @@ describe('@graph-om/sdk env schema', () => { emptyStringAsUndefined: true, }); - expect(env.GRAPH_OM_DEBUG).toBe(false); + expect(env.GRAPH_KIT_DEBUG).toBe(false); }); }); diff --git a/tests/schema_integration.test.ts b/tests/schema_integration.test.ts index 7c5c886..bfa7b46 100644 --- a/tests/schema_integration.test.ts +++ b/tests/schema_integration.test.ts @@ -1,8 +1,8 @@ -// @graph-om/tests/schema_integration.test.ts -// Cross-package test: validates the @graph-om/sdk schema DSL works with the Neo4j driver types +// @graph-kit/tests/schema_integration.test.ts +// Cross-package test: validates the @graph-kit/sdk schema DSL works with the Neo4j driver types -import type { DriverAdapter, GraphSchemaRegistry, NodeConfig } from '@graph-om/sdk'; -import { boolean, date, defineRel, node, number, schema, string } from '@graph-om/sdk'; +import type { DriverAdapter, GraphSchemaRegistry, NodeConfig } from '@graph-kit/sdk'; +import { boolean, date, defineRel, node, number, schema, string } from '@graph-kit/sdk'; import { describe, expect, it } from 'vitest'; describe('schema DSL + neo4j-driver integration', () => { diff --git a/turbo.json b/turbo.json index 01ebf21..6acedc2 100644 --- a/turbo.json +++ b/turbo.json @@ -57,6 +57,6 @@ "NEO4J_USER", "NEO4J_PASSWORD", "NEO4J_DATABASE", - "GRAPH_OM_DEBUG" + "GRAPH_KIT_DEBUG" ] } diff --git a/vitest.config.ts b/vitest.config.ts index 4abe02e..89c500b 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,7 +4,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ resolve: { alias: { - '@graph-om/sdk': path.resolve(__dirname, 'packages/sdk/src/index.ts'), + '@graph-kit/sdk': path.resolve(__dirname, 'packages/sdk/src/index.ts'), }, }, test: { From 4be4554a36a0b63cfc414980de1f33f7281f46fb Mon Sep 17 00:00:00 2001 From: Gabriel Fonseca Date: Tue, 10 Nov 2026 09:18:59 +0000 Subject: [PATCH 2/5] fix: increase @graph-kit/mcp require bundle size limit The rename from @graph-om to @graph-kit adds one character per @graph-kit occurrence, pushing @graph-kit/mcp (require) 23 B over its 1700 B limit. Increase limit to 1800 B with buffer. --- .size-limit.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limit.json b/.size-limit.json index adef96b..21c8d50 100644 --- a/.size-limit.json +++ b/.size-limit.json @@ -11,7 +11,7 @@ "path": "packages/mcp/dist/index.js", "gzip": true, "brotli": false, - "limit": "1700 B" + "limit": "1800 B" }, { "name": "@graph-kit/migrate (import)", From 41850c0adab4f0e3c9e102d727d4e29558512294 Mon Sep 17 00:00:00 2001 From: Gabriel Fonseca Date: Tue, 10 Nov 2026 09:25:06 +0000 Subject: [PATCH 3/5] fix: init command writes graph-kit.config.ts not graph.config.ts The CLI init command was scaffolding graph.config.ts but the test expects graph-kit.config.ts. Also fix generate.ts to prefer graph-kit.config.ts as config candidate, fix error message reference, and replace legacy metal.config.ts watch target. --- packages/cli/src/commands/generate.ts | 10 +++++----- packages/cli/src/commands/init.ts | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/commands/generate.ts b/packages/cli/src/commands/generate.ts index 2805eab..f6d8828 100644 --- a/packages/cli/src/commands/generate.ts +++ b/packages/cli/src/commands/generate.ts @@ -252,12 +252,12 @@ export function loadProjectConfig(projectRoot: string): LoadedProjectConfig { let zod = false; let exclude: string[] = []; - // Preferred config filename first, then the legacy graph-kit.config.* names. + // Preferred config filename first, then legacy fallbacks. const configCandidates = [ - path.join(projectRoot, 'graph.config.ts'), - path.join(projectRoot, 'graph.config.json'), path.join(projectRoot, 'graph-kit.config.ts'), path.join(projectRoot, 'graph-kit.config.json'), + path.join(projectRoot, 'graph.config.ts'), + path.join(projectRoot, 'graph.config.json'), ]; const configJsonPath = configCandidates.find((p) => p.endsWith('.json') && fs.existsSync(p)); @@ -305,7 +305,7 @@ export function runGenerate(projectRoot: string): GenerateResult { if (!fs.existsSync(schemaPath)) { raiseGraphError( `Schema file not found at ${schemaPath}. ` + - `Check the "schema" field in graph.config.ts or run \`graph-kit init\`.`, + `Check the "schema" field in graph-kit.config.ts or run \`graph-kit init\`.`, { code: 'invalid_config', statusCode: 400 }, ); } @@ -346,7 +346,7 @@ export async function generateCommand(options: GenerateOptions): Promise { if (options.watch) { const { schemaPath } = loadProjectConfig(projectRoot); - const watchTargets = [schemaPath, path.join(projectRoot, 'metal.config.ts')].filter((p) => + const watchTargets = [schemaPath, path.join(projectRoot, 'graph-kit.config.ts')].filter((p) => fs.existsSync(p), ); console.log('\n👀 Watching for changes... (Ctrl+C to stop)\n'); diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 3ebdd3e..c3b55a0 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -108,8 +108,8 @@ main().catch((error) => { fs.writeFileSync(path.join(targetDir, 'src', 'index.ts'), mainContent); - // Generate graph.config.ts — the single source of truth for Graph-Kit - const graphOmConfigContent = `import { defineConfig, env } from '@graph-kit/sdk'; + // Generate graph-kit.config.ts — the single source of truth for Graph-Kit + const graphKitConfigContent = `import { defineConfig, env } from '@graph-kit/sdk'; export default defineConfig({ schema: './src/schema.ts', @@ -127,7 +127,7 @@ export default defineConfig({ }); `; - fs.writeFileSync(path.join(targetDir, 'graph.config.ts'), graphOmConfigContent); + fs.writeFileSync(path.join(targetDir, 'graph-kit.config.ts'), graphKitConfigContent); const envContent = `NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j From 0aa338f2b25168f58164838e33118ea868e694f1 Mon Sep 17 00:00:00 2001 From: Gabriel Fonseca Date: Tue, 10 Nov 2026 09:47:13 +0000 Subject: [PATCH 4/5] chore: add CodeQL workflow for renamed repo Add explicit CodeQL analysis workflow so code scanning works correctly after the repository rename from graph-om to graph-kit. The previous repo-level default setup was tied to the old repo name and failed immediately on the renamed repo. --- .github/codeql-config.yml | 2 ++ .github/workflows/codeql.yml | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 .github/codeql-config.yml create mode 100644 .github/workflows/codeql.yml diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml new file mode 100644 index 0000000..f31ca01 --- /dev/null +++ b/.github/codeql-config.yml @@ -0,0 +1,2 @@ +# CodeQL configuration for graph-kit +# Uses the default set of queries for JavaScript and TypeScript. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..9e170f3 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,35 @@ +name: "CodeQL" + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: '0 11 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [javascript, typescript] + + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 From e8cf4351236d6dd11ecfaa3428a542742d309fbb Mon Sep 17 00:00:00 2001 From: Gabriel Fonseca Date: Tue, 10 Nov 2026 09:50:10 +0000 Subject: [PATCH 5/5] chore: remove CodeQL workflow (conflicts with repo default setup) Remove advanced CodeQL workflow files. CodeQL is configured at the GitHub repo level via default setup, which needs to be re-enabled in Settings > Security > Code scanning for the renamed graph-kit repo. An advanced-setup workflow conflicts with the enabled default setup. --- .github/codeql-config.yml | 2 -- .github/workflows/codeql.yml | 35 ----------------------------------- 2 files changed, 37 deletions(-) delete mode 100644 .github/codeql-config.yml delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml deleted file mode 100644 index f31ca01..0000000 --- a/.github/codeql-config.yml +++ /dev/null @@ -1,2 +0,0 @@ -# CodeQL configuration for graph-kit -# Uses the default set of queries for JavaScript and TypeScript. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 9e170f3..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - - cron: '0 11 * * 5' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [javascript, typescript] - - steps: - - name: Checkout repository - uses: actions/checkout@v7 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4