Skip to content

Commit

Permalink
feat(queries): BranchQueryHandler
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Nov 1, 2023
1 parent 890714d commit e18d07a
Show file tree
Hide file tree
Showing 18 changed files with 448 additions and 32 deletions.
1 change: 1 addition & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ ignore:
- '**/__mocks__/**'
- '**/__tests__/**'
- '**/index.ts'
- '**/types/'
- src/main.ts

profiling:
Expand Down
2 changes: 2 additions & 0 deletions .dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ bdougie
cefc
codecov
commitlintrc
cqrs
ddthh
dedupe
dessant
Expand All @@ -17,6 +18,7 @@ lcov
lintstagedrc
mkbuild
mlly
nestjs
nocheck
nvmrc
pathe
Expand Down
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ updates:
flex-development:
patterns:
- '@flex-development/*'
nestjs:
patterns:
- '@nestjs/*'
- rxjs
typescript-eslint:
patterns:
- '@typescript-eslint/*'
Expand Down
3 changes: 2 additions & 1 deletion .github/infrastructure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ repository:
automated_security_fixes: true
default_branch: main
delete_branch_on_merge: true
description: Create commits with the GitHub REST API
description: Create commits with the GitHub API
has_issues: true
has_projects: true
has_wiki: false
Expand All @@ -181,6 +181,7 @@ repository:
- commit
- commit-action
- github-api
- graphql
- typescript
visibility: public
vulnerability_alerts: true
Expand Down
5 changes: 5 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#!/bin/sh

set -e

# Pre-Commit Workflow
#
# References:
#
# - https://github.com/okonet/lint-staged#command-line-flags

yarn build
yarn check:types:build
git add dist/** --verbose
cross-env LINT_STAGED=1 lint-staged --config=.lintstagedrc.json --relative --verbose
6 changes: 1 addition & 5 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,5 @@
],
"**/*.{cts,mts,ts}": "vitest typecheck --changed --run",
"**/yarn.lock": "yarn dedupe --check",
"src/**/*.ts": [
"vitest --changed --coverage --run",
"yarn build",
"bash -c tsc -p tsconfig.build.json"
]
"src/**/*.ts": "vitest --changed --coverage --run"
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[![vitest](https://img.shields.io/badge/-vitest-6e9f18?style=flat&logo=vitest&logoColor=ffffff)](https://vitest.dev/)
[![yarn](https://img.shields.io/badge/-yarn-2c8ebb?style=flat&logo=yarn&logoColor=ffffff)](https://yarnpkg.com/)

Create commits with the [GitHub REST API][1]
Create commits with the [GitHub API][1]

## Contents

Expand All @@ -36,4 +36,4 @@ Create commits with the [GitHub REST API][1]

**TODO**: outputs

[1]: https://docs.github.com/rest/git/commits#create-a-commit
[1]: https://docs.github.com/graphql/reference/mutations#createcommitonbranch
7 changes: 7 additions & 0 deletions build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ const config: Config = defineBuildConfig({
charset: 'utf8',
conditions: tsconfig.compilerOptions.customConditions,
dts: false,
external: [
'@nestjs/microservices',
'@nestjs/platform-express',
'@nestjs/websockets',
'class-transformer',
'class-validator'
],
platform: 'node',
source: 'src/main.ts',
sourcemap: true,
Expand Down
34 changes: 19 additions & 15 deletions loader.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ export const load = async (url, context) => {
*/
let source = await mlly.getSource(url, { format: context.format })

// emit decorator metadata
DECORATOR_REGEX.lastIndex = 0
if (DECORATOR_REGEX.test(source)) {
const { outputText } = ts.transpileModule(source, {
compilerOptions: tscu.normalizeCompilerOptions({
...compilerOptions,
inlineSourceMap: true
}),
fileName: url
})

source = outputText
}

// transform typescript files
if (/^\.(?:cts|mts|tsx?)$/.test(ext) && !/\.d\.(?:cts|mts|ts)$/.test(url)) {
// push require condition for .cts files and update format
Expand All @@ -96,20 +110,6 @@ export const load = async (url, context) => {
parent: url
})

// emit decorator metadata
DECORATOR_REGEX.lastIndex = 0
if (DECORATOR_REGEX.test(source)) {
const { outputText } = ts.transpileModule(source, {
compilerOptions: tscu.normalizeCompilerOptions({
...compilerOptions,
sourceMap: false
}),
fileName: url
})

source = outputText
}

// transpile source code
const { code } = await esbuild.transform(source, {
format: 'esm',
Expand All @@ -126,7 +126,11 @@ export const load = async (url, context) => {
source = code
}

return { format: context.format, shortCircuit: true, source }
return {
format: context.format,
shortCircuit: true,
source: tutils.ifelse(context.format === mlly.Format.COMMONJS, null, source)
}
}

/**
Expand Down
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@flex-development/commit-action",
"description": "Create commits with the GitHub REST API",
"description": "Create commits with the GitHub API",
"version": "0.0.0",
"keywords": [],
"license": "BSD-3-Clause",
Expand Down Expand Up @@ -75,7 +75,12 @@
"@flex-development/pathe": "2.0.0",
"@flex-development/tsconfig-utils": "2.0.2",
"@flex-development/tutils": "6.0.0-alpha.25",
"@octokit/types": "12.1.1",
"@nestjs/common": "10.2.7",
"@nestjs/core": "10.2.7",
"@nestjs/cqrs": "10.2.6",
"@nestjs/testing": "10.2.7",
"@octokit/core": "5.0.1",
"@octokit/graphql-schema": "14.39.1",
"@types/chai": "4.3.9",
"@types/eslint": "8.44.6",
"@types/is-ci": "3.0.3",
Expand Down Expand Up @@ -105,6 +110,8 @@
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-unicorn": "49.0.0",
"eslint-plugin-yml": "1.10.0",
"graphql": "16.8.1",
"graphql-tag": "2.12.6",
"growl": "1.10.5",
"husky": "8.0.3",
"is-ci": "3.0.1",
Expand All @@ -113,6 +120,8 @@
"nock": "13.3.7",
"node-notifier": "10.0.1",
"prettier": "3.0.3",
"reflect-metadata": "0.1.13",
"rxjs": "7.8.1",
"sh-syntax": "0.4.1",
"trash-cli": "5.0.0",
"ts-dedent": "2.2.0",
Expand Down
70 changes: 70 additions & 0 deletions src/queries/__tests__/branch.handler.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* @file Unit Tests - BranchQueryHandler
* @module commit-action/queries/tests/unit/BranchQueryHandler
*/

import * as github from '@actions/github'
import pathe from '@flex-development/pathe'
import { join } from '@flex-development/tutils'
import { Test } from '@nestjs/testing'
import { Octokit } from '@octokit/core'
import TestSubject from '../branch.handler'
import BranchQuery from '../branch.query'

describe('unit:queries/BranchQueryHandler', () => {
let subject: TestSubject

beforeAll(async () => {
subject = (await Test.createTestingModule({
providers: [
TestSubject,
{
provide: Octokit,
useValue: github.getOctokit(process.env.GITHUB_TOKEN!, {
log: {
debug: vi.fn().mockName('octokit.log.debug'),
error: vi.fn().mockName('octokit.log.error'),
info: vi.fn().mockName('octokit.log.info'),
warn: vi.fn().mockName('octokit.log.warn')
}
})
}
]
}).compile()).get(TestSubject)
})

describe('execute', () => {
let owner: string
let repo: string

beforeAll(() => {
owner = 'flex-development'
repo = 'commit-action'
})

it('should return branch payload if query.ref is found', async () => {
// Arrange
const ref: string = 'main'
const query: BranchQuery = new BranchQuery({ owner, ref, repo })

// Act
const result = await subject.execute(query)

// Expect
expect(result).to.have.keys(['head', 'name', 'repository'])
expect(result).toMatchObject({
head: <string>expect.any(String),
name: ref,
repository: join([owner, repo], pathe.sep)
})
})

it('should return null if query.ref is not found', async () => {
// Arrange
const query: BranchQuery = new BranchQuery({ owner, ref: '', repo })

// Act + Expect
expect(await subject.execute(query)).to.be.null
})
})
})
95 changes: 95 additions & 0 deletions src/queries/branch.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* @file Queries - BranchQueryHandler
* @module commit-action/queries/BranchQueryHandler
*/

import type { Branch } from '#src/types'
import { isNIL, type Nullable } from '@flex-development/tutils'
import { QueryHandler, type IQueryHandler } from '@nestjs/cqrs'
import { Octokit } from '@octokit/core'
import type { Repository as Payload } from '@octokit/graphql-schema'
import * as graphql from 'graphql'
import gql from 'graphql-tag'
import BranchQuery from './branch.query'

/**
* Branch query handler.
*
* @see {@linkcode Branch}
* @see {@linkcode BranchQuery}
*
* @class
* @implements {IQueryHandler<BranchQuery,Nullable<Branch>>}
*/
@QueryHandler(BranchQuery)
class BranchQueryHandler
implements IQueryHandler<BranchQuery, Nullable<Branch>> {
/**
* GraphQL query.
*
* @see {@linkcode graphql.DocumentNode}
* @see https://docs.github.com/graphql/reference/objects#repository
*
* @protected
* @readonly
* @instance
* @member {graphql.DocumentNode} operation
*/
protected readonly operation: graphql.DocumentNode

/**
* Create a new branch query handler.
*
* @see {@linkcode Octokit}
*
* @param {Octokit} octokit - Hydrated octokit client
*/
constructor(protected readonly octokit: Octokit) {
this.operation = gql`
query ($owner: String!, $ref: String!, $repo: String!) {
payload: repository(name: $repo, owner: $owner) {
ref(qualifiedName: $ref) {
name
repository { nameWithOwner }
target { oid }
}
}
}
`
}

/**
* Execute a branch query.
*
* @see {@linkcode Branch}
* @see {@linkcode BranchQuery}
*
* @public
* @async
*
* @param {BranchQuery} query - Query to execute
* @return {Promise<Nullable<Branch>>} Branch payload or `null`
*/
public async execute(query: BranchQuery): Promise<Nullable<Branch>> {
// fetch branch reference from repository
const { payload } = await this.octokit.graphql<{ payload: Payload }>({
owner: query.owner,
query: graphql.print(this.operation),
ref: query.ref,
repo: query.repo
})

// format branch payload if reference was found
if (!isNIL(payload.ref) && !isNIL(payload.ref.target)) {
return {
head: payload.ref.target.oid,
name: payload.ref.name,
repository: payload.ref.repository.nameWithOwner
}
}

return null
}
}

export default BranchQueryHandler
1 change: 1 addition & 0 deletions src/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
* @module commit-action/queries
*/

export { default as BranchQueryHandler } from './branch.handler'
export { default as BranchQuery } from './branch.query'
22 changes: 22 additions & 0 deletions src/types/__tests__/branch.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @file Type Tests - Branch
* @module commit-action/types/tests/unit-d/Branch
*/

import type TestSubject from '../branch'

describe('unit-d:types/Branch', () => {
it('should match [head: string]', () => {
expectTypeOf<TestSubject>().toHaveProperty('head').toEqualTypeOf<string>()
})

it('should match [name: string]', () => {
expectTypeOf<TestSubject>().toHaveProperty('name').toEqualTypeOf<string>()
})

it('should match [repository: string]', () => {
expectTypeOf<TestSubject>()
.toHaveProperty('repository')
.toEqualTypeOf<string>()
})
})
Loading

0 comments on commit e18d07a

Please sign in to comment.