diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml new file mode 100644 index 000000000..2868a1bcd --- /dev/null +++ b/.github/workflows/auto-release.yml @@ -0,0 +1,143 @@ +name: auto-release + +on: + push: + branches: + - main + paths-ignore: + - "**.md" + - "website/**" + - "docs/**" + - ".github/**" + - "!.github/workflows/**" + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + +jobs: + auto-release: + name: Auto Release + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, 'release:')" + permissions: + contents: write + pull-requests: read + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Get latest release + id: latest_release + run: | + # Get the latest release tag, fallback to v0.0.0 if none exists + latest_tag=$(git tag --sort=-version:refname | head -n1 || echo "v0.0.0") + echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT + echo "Latest release tag: $latest_tag" + + - name: Get commits since last release + id: commits + run: | + latest_tag="${{ steps.latest_release.outputs.latest_tag }}" + if [ "$latest_tag" = "v0.0.0" ]; then + # If no previous release, get all commits + commits=$(git log --oneline --pretty=format:"%s" | head -10) + else + # Get commits since last release + commits=$(git log ${latest_tag}..HEAD --oneline --pretty=format:"%s") + fi + + echo "Commits since $latest_tag:" + echo "$commits" + + # Check if there are any commits to release + if [ -z "$commits" ]; then + echo "No new commits to release" + echo "should_release=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "should_release=true" >> $GITHUB_OUTPUT + + - name: Determine version bump type + id: bump_type + if: steps.commits.outputs.should_release == 'true' + run: | + latest_tag="${{ steps.latest_release.outputs.latest_tag }}" + commits=$(git log ${latest_tag}..HEAD --oneline --pretty=format:"%s" || git log --oneline --pretty=format:"%s" | head -10) + + # Default to patch + bump_type="patch" + + # Check for breaking changes (major) + if echo "$commits" | grep -qE "^[^:]+!:|BREAKING CHANGE"; then + bump_type="major" + # Check for features (minor) + elif echo "$commits" | grep -qE "^feat(\(.+\))?:"; then + bump_type="minor" + # Check for fixes and other changes (patch) + elif echo "$commits" | grep -qE "^(fix|perf|refactor|style|docs|test|build|ci|chore)(\(.+\))?:"; then + bump_type="patch" + fi + + echo "Determined bump type: $bump_type" + echo "bump_type=$bump_type" >> $GITHUB_OUTPUT + + - name: Bump version + id: version_bump + if: steps.commits.outputs.should_release == 'true' + run: | + bump_type="${{ steps.bump_type.outputs.bump_type }}" + + # Get current version from package.json + current_version=$(node -p "require('./package.json').version") + echo "Current version: $current_version" + + # Bump version using npm + npm version $bump_type --no-git-tag-version + + # Get new version + new_version=$(node -p "require('./package.json').version") + echo "New version: $new_version" + echo "new_version=$new_version" >> $GITHUB_OUTPUT + + - name: Commit version bump and create tag + if: steps.commits.outputs.should_release == 'true' + run: | + new_version="${{ steps.version_bump.outputs.new_version }}" + + # Commit the version bump + git add package.json + git commit -m "release: $new_version" + + # Create and push tag + git tag "v$new_version" + git push origin main + git push origin "v$new_version" + + echo "Created and pushed tag v$new_version" + + - name: Summary + run: | + if [ "${{ steps.commits.outputs.should_release }}" = "true" ]; then + echo "✅ Auto-release completed!" + echo "New version: ${{ steps.version_bump.outputs.new_version }}" + echo "Tag created: v${{ steps.version_bump.outputs.new_version }}" + echo "" + echo "The check and release workflows will now run automatically." + else + echo "ℹ️ No new commits to release - skipping auto-release" + fi diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 151e3662d..93eb88288 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -2,13 +2,11 @@ name: check on: push: - branches: - - master tags: - v* pull_request: branches: - - master + - main concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -45,7 +43,7 @@ jobs: uses: pozetroninc/github-action-get-latest-release@master id: version_v_github with: - owner: MichalLytek + owner: scope3data repo: type-graphql excludes: prerelease, draft @@ -105,8 +103,6 @@ jobs: check: name: Build & Lint & Test - needs: version - if: always() && (needs.version.result == 'success' || needs.version.result == 'skipped') runs-on: ubuntu-latest strategy: fail-fast: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 44c87475d..485f726b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,20 +11,40 @@ concurrency: group: ${{ github.workflow }} cancel-in-progress: true +permissions: + pull-requests: write + contents: read + packages: write + jobs: release: - name: Release package on NPM + name: Release package on GitHub Packages runs-on: ubuntu-latest - if: github.event.workflow_run.conclusion == 'success' && github.ref_name == 'master' && startsWith(github.event.workflow_run.head_branch, 'v') + if: github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'v') permissions: contents: write id-token: write + packages: write steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ github.event.workflow_run.head_branch }} + - name: Verify version validation passed + env: + TYPE_GRAPHQL_VERSION: ${{ github.event.workflow_run.head_branch }} + run: | + echo "Verifying release for version: $TYPE_GRAPHQL_VERSION" + + # Ensure this is a valid version tag format + if ! printf "%s\n" "$TYPE_GRAPHQL_VERSION" | grep -q -P '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-(alpha|beta|rc)\.(0|[1-9][0-9]*))?$'; then + printf '[ERROR]: Invalid version tag format (%s)\n' "$TYPE_GRAPHQL_VERSION" + exit 1 + fi + + echo "✅ Version tag format is valid" + - name: Determine if version is prerelease id: prerelease env: @@ -43,7 +63,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 22.x - registry-url: "https://registry.npmjs.org" + registry-url: "https://npm.pkg.github.com" - name: Install latest npm run: | @@ -77,7 +97,7 @@ jobs: - name: Publish env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TYPE_GRAPHQL_PRERELEASE: ${{ steps.prerelease.outputs.value }} run: | _tag= diff --git a/.npmrc b/.npmrc index 59b73ee7e..1b382ce9d 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1,3 @@ engine-strict=true @scope3data:registry=https://npm.pkg.github.com -//npm.pkg.github.com/:_authToken=${NPM_TOKEN} +//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN} diff --git a/README.md b/README.md index 171c8581a..bcb3e3127 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,80 @@ ![logo](./images/logo.png) +--- + +## Performance-Optimized Fork by [Scope3](https://scope3.com/home) + +> **Context**: This is a high-performance fork maintained by [Scope3](https://github.com/scope3data) with significant optimization improvements. Our changes have been submitted as [PR #1779](https://github.com/MichalLytek/type-graphql/pull/1779) to the original repository but remain unmerged after 6+ months. + +### Performance Improvements + +#### What’s Different in the Scope3 Fork? + +This fork introduces a major refactor of the TypeGraphQL metadata build process, focused on dramatically improving performance for large schemas. It works very well! Scope3 has been running this fork in production for over 6 months, dropping our schema generation time from 4-5 minutes to under 10 seconds in our K8s deployments. + +**Problem:** +Schema generation in the upstream project was exponentially slow for large schemas, taking 30+ seconds with 3k-15k metadata objects due to repeated O(n) array `.filter()` lookups. + +**Scope3 Solution:** +We replaced all repeated array lookups with O(1) HashMap-based caching. + +- Added cache initialization for all major metadata types (object types, fields, params, middlewares, directives, resolver classes, etc.). +- All metadata lookups now use these caches instead of array `.filter()` calls. +- Refactored resolver and field metadata construction to leverage these caches. + +**Technical Details:** + +- Introduced `Map` caches for object types, fields, params, middlewares, directives, and resolver classes. +- Added an `initCache()` method to populate these caches before schema building. +- All metadata construction logic now uses these caches for instant lookup. + +**Performance Impact:** + +- Schema generation time reduced from tens of seconds to milliseconds for large schemas. +- Example: + - `buildClassMetadata`: 31.3s → 268ms (116x faster) + - `buildFieldResolverMetadata`: 314ms → 39ms (8x faster) + - `buildResolversMetadata`: 1.4s → 126ms (11x faster) + +**Compatibility:** + +- The fork remains 100% backward compatible with the original TypeGraphQL API. +- All original TypeGraphQL tests pass with these changes. +- Scope3 has been running this fork in production for over 6 months. +- All recent upstream changes are documentation-only (sponsor updates). + +--- + +If you want more technical details or code samples, see the source or reach out to Scope3! + +### Installation + +```bash +# Add to .npmrc +@scope3data:registry=https://npm.pkg.github.com + +# Install with npm +npm install @scope3data/type-graphql + +# Install with Yarn +yarn add @scope3data/type-graphql + +# Install with PNPM +pnpm add @scope3data/type-graphql +``` + +### What's Coming + +- Prisma 6 support – Upgrading to the latest Prisma version +- GraphQL 16.11 – Latest GraphQL version with improved performance and features + +### Compatibility + +100% backward compatible – drop-in replacement for the original `type-graphql` package. + +--- + # TypeGraphQL [![release](https://github.com/MichalLytek/type-graphql/actions/workflows/release.yml/badge.svg)](https://github.com/MichalLytek/type-graphql/actions/workflows/release.yml) diff --git a/package.json b/package.json index 39d3ebc83..dc6f6cb8d 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "type-graphql", + "name": "@scope3data/type-graphql", "version": "2.0.0-rc.3", "private": false, "description": "Create GraphQL schema and resolvers with TypeScript, using classes and decorators!", @@ -15,11 +15,11 @@ ], "homepage": "https://typegraphql.com", "bugs": { - "url": "https://github.com/MichalLytek/type-graphql/issues" + "url": "https://github.com/scope3data/type-graphql/issues" }, "repository": { "type": "git", - "url": "git+https://github.com/MichalLytek/type-graphql.git" + "url": "git+https://github.com/scope3data/type-graphql.git" }, "funding": [ {