wip: cli and changelog commit upload
This commit is contained in:
parent
a14cbd4437
commit
b182329146
66
apps/api/src/changelog/commit/byId.ts
Normal file
66
apps/api/src/changelog/commit/byId.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { changelog, changelog_version, db } from '@boring.tools/database'
|
||||
import { VersionByIdParams, VersionOutput } from '@boring.tools/schema'
|
||||
import { createRoute } from '@hono/zod-openapi'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
|
||||
export const byId = createRoute({
|
||||
method: 'get',
|
||||
path: '/:id',
|
||||
request: {
|
||||
params: VersionByIdParams,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: VersionOutput,
|
||||
},
|
||||
},
|
||||
description: 'Return version by id',
|
||||
},
|
||||
400: {
|
||||
description: 'Bad Request',
|
||||
},
|
||||
500: {
|
||||
description: 'Internal Server Error',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const byIdFunc = async ({
|
||||
userId,
|
||||
id,
|
||||
}: {
|
||||
userId: string
|
||||
id: string
|
||||
}) => {
|
||||
const versionResult = await db.query.changelog_version.findFirst({
|
||||
where: eq(changelog_version.id, id),
|
||||
with: {
|
||||
commits: true,
|
||||
},
|
||||
})
|
||||
|
||||
if (!versionResult) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (!versionResult.changelogId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const changelogResult = await db.query.changelog.findMany({
|
||||
where: and(eq(changelog.userId, userId)),
|
||||
columns: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
|
||||
const changelogIds = changelogResult.map((cl) => cl.id)
|
||||
|
||||
if (!changelogIds.includes(versionResult.changelogId)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return versionResult
|
||||
}
|
60
apps/api/src/changelog/commit/create.ts
Normal file
60
apps/api/src/changelog/commit/create.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { changelog, changelog_commit, db } from '@boring.tools/database'
|
||||
import { CommitCreateInput, CommitCreateOutput } from '@boring.tools/schema'
|
||||
import { createRoute, type z } from '@hono/zod-openapi'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { HTTPException } from 'hono/http-exception'
|
||||
import type { changelogCommitApi } from '.'
|
||||
import { verifyAuthentication } from '../../utils/authentication'
|
||||
|
||||
export const route = createRoute({
|
||||
method: 'post',
|
||||
path: '/',
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
'application/json': { schema: CommitCreateInput },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
201: {
|
||||
content: {
|
||||
'application/json': { schema: CommitCreateOutput },
|
||||
},
|
||||
description: 'Commits created',
|
||||
},
|
||||
400: {
|
||||
description: 'Bad Request',
|
||||
},
|
||||
500: {
|
||||
description: 'Internal Server Error',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const regsiterCommitCreate = (api: typeof changelogCommitApi) => {
|
||||
return api.openapi(route, async (c) => {
|
||||
const userId = verifyAuthentication(c)
|
||||
|
||||
const data: z.infer<typeof CommitCreateInput> = await c.req.json()
|
||||
|
||||
const changelogResult = await db.query.changelog.findFirst({
|
||||
where: and(
|
||||
eq(changelog.id, data[0].changelogId),
|
||||
eq(changelog.userId, userId),
|
||||
),
|
||||
})
|
||||
|
||||
if (!changelogResult) {
|
||||
throw new HTTPException(404, { message: 'Not Found' })
|
||||
}
|
||||
|
||||
const [result] = await db.insert(changelog_commit).values(data).returning()
|
||||
|
||||
if (!result) {
|
||||
throw new HTTPException(404, { message: 'Not Found' })
|
||||
}
|
||||
|
||||
return c.json(result, 200)
|
||||
})
|
||||
}
|
63
apps/api/src/changelog/commit/delete.ts
Normal file
63
apps/api/src/changelog/commit/delete.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { changelog, changelog_version, db } from '@boring.tools/database'
|
||||
import { GeneralOutput } from '@boring.tools/schema'
|
||||
import { createRoute } from '@hono/zod-openapi'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { HTTPException } from 'hono/http-exception'
|
||||
|
||||
export const remove = createRoute({
|
||||
method: 'delete',
|
||||
path: '/:id',
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: GeneralOutput,
|
||||
},
|
||||
},
|
||||
description: 'Removes a version by id',
|
||||
},
|
||||
404: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: GeneralOutput,
|
||||
},
|
||||
},
|
||||
description: 'Version not found',
|
||||
},
|
||||
500: {
|
||||
description: 'Internal Server Error',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const removeFunc = async ({
|
||||
userId,
|
||||
id,
|
||||
}: {
|
||||
userId: string
|
||||
id: string
|
||||
}) => {
|
||||
const changelogResult = await db.query.changelog.findMany({
|
||||
where: and(eq(changelog.userId, userId)),
|
||||
with: {
|
||||
versions: {
|
||||
where: eq(changelog_version.id, id),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const findChangelog = changelogResult.find((change) =>
|
||||
change.versions.find((ver) => ver.id === id),
|
||||
)
|
||||
|
||||
if (!findChangelog?.versions.length) {
|
||||
throw new HTTPException(404, {
|
||||
message: 'Version not found',
|
||||
})
|
||||
}
|
||||
|
||||
return db
|
||||
.delete(changelog_version)
|
||||
.where(and(eq(changelog_version.id, id)))
|
||||
.returning()
|
||||
}
|
122
apps/api/src/changelog/commit/index.ts
Normal file
122
apps/api/src/changelog/commit/index.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { OpenAPIHono } from '@hono/zod-openapi'
|
||||
import type { Variables } from '../..'
|
||||
import type { ContextModule } from '../../utils/sentry'
|
||||
import { regsiterCommitCreate } from './create'
|
||||
|
||||
export const changelogCommitApi = new OpenAPIHono<{ Variables: Variables }>()
|
||||
|
||||
const module: ContextModule = {
|
||||
name: 'changelog',
|
||||
sub_module: 'version',
|
||||
}
|
||||
|
||||
regsiterCommitCreate(changelogCommitApi)
|
||||
|
||||
// app.openapi(create, async (c) => {
|
||||
// const userId = verifyAuthentication(c)
|
||||
// try {
|
||||
// const payload = await c.req.json()
|
||||
// const result = await createFunc({ userId, payload })
|
||||
|
||||
// if (!result) {
|
||||
// return c.json({ message: 'Version not created' }, 400)
|
||||
// }
|
||||
|
||||
// return c.json(result, 201)
|
||||
// } catch (error) {
|
||||
// return captureSentry({
|
||||
// c,
|
||||
// error,
|
||||
// module,
|
||||
// user: {
|
||||
// id: userId,
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
|
||||
/* app.openapi(byId, async (c) => {
|
||||
const userId = verifyAuthentication(c)
|
||||
try {
|
||||
const id = c.req.param('id')
|
||||
const result = await byIdFunc({ userId, id })
|
||||
|
||||
if (!result) {
|
||||
return c.json({ message: 'Version not found' }, 404)
|
||||
}
|
||||
|
||||
// Ensure all required properties are present and non-null
|
||||
return c.json(
|
||||
{
|
||||
...result,
|
||||
changelogId: result.changelogId || '',
|
||||
version: result.version || '',
|
||||
status: result.status || 'draft',
|
||||
releasedAt: result.releasedAt,
|
||||
commits: result.commits || [],
|
||||
markdown: result.markdown || '',
|
||||
},
|
||||
200,
|
||||
)
|
||||
} catch (error) {
|
||||
return captureSentry({
|
||||
c,
|
||||
error,
|
||||
module,
|
||||
user: {
|
||||
id: userId,
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
app.openapi(update, async (c) => {
|
||||
const userId = verifyAuthentication(c)
|
||||
try {
|
||||
const id = c.req.param('id')
|
||||
|
||||
if (!id) {
|
||||
return c.json({ message: 'Version not found' }, 404)
|
||||
}
|
||||
|
||||
const result = await updateFunc({
|
||||
userId,
|
||||
payload: await c.req.json(),
|
||||
id,
|
||||
})
|
||||
|
||||
return c.json(result)
|
||||
} catch (error) {
|
||||
return captureSentry({
|
||||
c,
|
||||
error,
|
||||
module,
|
||||
user: {
|
||||
id: userId,
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
app.openapi(remove, async (c) => {
|
||||
const userId = verifyAuthentication(c)
|
||||
try {
|
||||
const id = c.req.param('id')
|
||||
const result = await removeFunc({ userId, id })
|
||||
|
||||
if (result.length === 0) {
|
||||
return c.json({ message: 'Version not found' }, 404)
|
||||
}
|
||||
|
||||
return c.json({ message: 'Version removed' })
|
||||
} catch (error) {
|
||||
return captureSentry({
|
||||
c,
|
||||
error,
|
||||
module,
|
||||
user: {
|
||||
id: userId,
|
||||
},
|
||||
})
|
||||
}
|
||||
}) */
|
72
apps/api/src/changelog/commit/update.ts
Normal file
72
apps/api/src/changelog/commit/update.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { changelog, changelog_version, db } from '@boring.tools/database'
|
||||
import { VersionUpdateInput, VersionUpdateOutput } from '@boring.tools/schema'
|
||||
import { createRoute, type z } from '@hono/zod-openapi'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { HTTPException } from 'hono/http-exception'
|
||||
|
||||
export const update = createRoute({
|
||||
method: 'put',
|
||||
path: '/:id',
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
'application/json': { schema: VersionUpdateInput },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': { schema: VersionUpdateOutput },
|
||||
},
|
||||
description: 'Return updated version',
|
||||
},
|
||||
400: {
|
||||
description: 'Bad Request',
|
||||
},
|
||||
500: {
|
||||
description: 'Internal Server Error',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const updateFunc = async ({
|
||||
userId,
|
||||
payload,
|
||||
id,
|
||||
}: {
|
||||
userId: string
|
||||
payload: z.infer<typeof VersionUpdateInput>
|
||||
id: string
|
||||
}) => {
|
||||
const changelogResult = await db.query.changelog.findMany({
|
||||
where: and(eq(changelog.userId, userId)),
|
||||
with: {
|
||||
versions: {
|
||||
where: eq(changelog_version.id, id),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const findChangelog = changelogResult.find((change) =>
|
||||
change.versions.find((ver) => ver.id === id),
|
||||
)
|
||||
|
||||
if (!findChangelog?.versions.length) {
|
||||
throw new HTTPException(404, {
|
||||
message: 'Version not found',
|
||||
})
|
||||
}
|
||||
|
||||
const [versionUpdateResult] = await db
|
||||
.update(changelog_version)
|
||||
.set({
|
||||
status: payload.status,
|
||||
markdown: payload.markdown,
|
||||
releasedAt: payload.releasedAt ? new Date(payload.releasedAt) : null,
|
||||
})
|
||||
.where(and(eq(changelog_version.id, id)))
|
||||
.returning()
|
||||
|
||||
return versionUpdateResult
|
||||
}
|
@ -5,6 +5,7 @@ import { apiReference } from '@scalar/hono-api-reference'
|
||||
import { cors } from 'hono/cors'
|
||||
|
||||
import changelog from './changelog'
|
||||
import { changelogCommitApi } from './changelog/commit'
|
||||
import version from './changelog/version'
|
||||
import user from './user'
|
||||
|
||||
@ -36,6 +37,7 @@ app.use('/v1/*', authentication)
|
||||
app.route('/v1/user', user)
|
||||
app.route('/v1/changelog', changelog)
|
||||
app.route('/v1/changelog/version', version)
|
||||
app.route('/v1/changelog/commit', changelogCommitApi)
|
||||
app.route('/v1/page', pageApi)
|
||||
|
||||
app.doc('/openapi.json', {
|
||||
|
@ -26,6 +26,7 @@
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hook-form": "^7.53.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"usehooks-ts": "^3.1.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -9,15 +9,26 @@ import {
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from '@boring.tools/ui'
|
||||
import { Link } from '@tanstack/react-router'
|
||||
import { Link, useLocation } from '@tanstack/react-router'
|
||||
import { ChevronRightIcon, FileStackIcon, PlusIcon } from 'lucide-react'
|
||||
import { useEffect } from 'react'
|
||||
import { useLocalStorage } from 'usehooks-ts'
|
||||
import { useChangelogList } from '../hooks/useChangelog'
|
||||
|
||||
export const SidebarChangelog = () => {
|
||||
const location = useLocation()
|
||||
const [value, setValue] = useLocalStorage('sidebar-changelog-open', false)
|
||||
const { data, error } = useChangelogList()
|
||||
|
||||
useEffect(() => {
|
||||
const firstElement = location.href.split('/')[1]
|
||||
if (firstElement === 'changelog') {
|
||||
setValue(true)
|
||||
}
|
||||
}, [location, setValue])
|
||||
|
||||
return (
|
||||
<Collapsible asChild>
|
||||
<Collapsible asChild open={value} onOpenChange={() => setValue(!value)}>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild tooltip="Changelog">
|
||||
<Link
|
||||
|
@ -9,15 +9,26 @@ import {
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from '@boring.tools/ui'
|
||||
import { Link } from '@tanstack/react-router'
|
||||
import { Link, useLocation } from '@tanstack/react-router'
|
||||
import { ChevronRightIcon, NotebookTextIcon, PlusIcon } from 'lucide-react'
|
||||
import { useEffect } from 'react'
|
||||
import { useLocalStorage } from 'usehooks-ts'
|
||||
import { usePageList } from '../hooks/usePage'
|
||||
|
||||
export const SidebarPage = () => {
|
||||
const location = useLocation()
|
||||
const [value, setValue] = useLocalStorage('sidebar-page-open', false)
|
||||
const { data, error } = usePageList()
|
||||
|
||||
useEffect(() => {
|
||||
const firstElement = location.href.split('/')[1]
|
||||
if (firstElement === 'page') {
|
||||
setValue(true)
|
||||
}
|
||||
}, [location, setValue])
|
||||
|
||||
return (
|
||||
<Collapsible asChild>
|
||||
<Collapsible asChild open={value} onOpenChange={() => setValue(!value)}>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild tooltip="Page">
|
||||
<Link to="/page" activeProps={{ className: 'bg-sidebar-accent' }}>
|
||||
|
@ -13,7 +13,6 @@ import { useChangelogById } from '../hooks/useChangelog'
|
||||
const Component = () => {
|
||||
const { id } = Route.useParams()
|
||||
const { data, error, isPending, refetch } = useChangelogById({ id })
|
||||
console.log(data)
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex items-center justify-center mt-32 flex-col">
|
||||
@ -65,16 +64,7 @@ const Component = () => {
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={'ghost'}>
|
||||
<Globe2Icon strokeWidth={1.5} />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Public Page</p>
|
||||
</TooltipContent>
|
||||
</Tooltip> */}
|
||||
*/}
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
175
apps/cli/.gitignore
vendored
Normal file
175
apps/cli/.gitignore
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
|
||||
# Logs
|
||||
|
||||
logs
|
||||
_.log
|
||||
npm-debug.log_
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Caches
|
||||
|
||||
.cache
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# Runtime data
|
||||
|
||||
pids
|
||||
_.pid
|
||||
_.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
15
apps/cli/README.md
Normal file
15
apps/cli/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# cli
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run src/index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.1.21. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
11
apps/cli/package.json
Normal file
11
apps/cli/package.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@boring.tools/cli",
|
||||
"module": "src/index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
70
apps/cli/src/index.ts
Normal file
70
apps/cli/src/index.ts
Normal file
@ -0,0 +1,70 @@
|
||||
#! /usr/bin/env bun
|
||||
import { parseArgs } from 'node:util'
|
||||
import semver from 'semver'
|
||||
import { z } from 'zod'
|
||||
import { git_log } from './utils/git_log'
|
||||
//import { pushCommits } from './pushCommits'
|
||||
|
||||
const ENV_VERSION = Bun.env.CHANGELOG_VERSION
|
||||
const ENV_ID = Bun.env.CHANGELOG_ID
|
||||
const ENV_TOKEN = Bun.env.CHANGELOG_TOKEN
|
||||
|
||||
const schema = z.object({
|
||||
title: z.string().optional(),
|
||||
version: z.string().optional(),
|
||||
token: z.string(),
|
||||
changelogId: z.string(),
|
||||
})
|
||||
export type Arguments = z.infer<typeof schema>
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: Bun.argv,
|
||||
options: {
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
version: {
|
||||
type: 'string',
|
||||
},
|
||||
token: {
|
||||
type: 'string',
|
||||
},
|
||||
changelogId: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
strict: true,
|
||||
allowPositionals: true,
|
||||
})
|
||||
|
||||
const mappedArguments = {
|
||||
...values,
|
||||
version: values.version || ENV_VERSION,
|
||||
token: values.token || ENV_TOKEN,
|
||||
changelogId: values.changelogId || ENV_ID,
|
||||
}
|
||||
|
||||
const args = schema.safeParse(mappedArguments)
|
||||
|
||||
/*if (!args.success) {
|
||||
console.error(
|
||||
`@changelog/cli: Missing arguemnts: ${args.error.errors
|
||||
.map((error) => error.path[0])
|
||||
.join(', ')}`,
|
||||
)
|
||||
process.exit(1)
|
||||
} */
|
||||
|
||||
// const version = semver.coerce(result.data.version);
|
||||
|
||||
// // Check for correct semver
|
||||
// if (!version) {
|
||||
// console.error(
|
||||
// "@changelog/cli: Invalid version. Please provide a valid semver version."
|
||||
// );
|
||||
// process.exit(1);
|
||||
// }
|
||||
|
||||
//pushCommits(args.data)
|
||||
|
||||
git_log('')
|
45
apps/cli/src/utils/git_log.ts
Normal file
45
apps/cli/src/utils/git_log.ts
Normal file
@ -0,0 +1,45 @@
|
||||
const GITFORMAT = `--pretty=format:{
|
||||
"commit": "%h",
|
||||
"parent": "%p",
|
||||
"refs": "%D",
|
||||
"subject": "%s",
|
||||
"notes": "%N",
|
||||
"body": "%b",
|
||||
"author": { "name": "%aN", "email": "%aE", "date": "%ad" },
|
||||
"commiter": { "name": "%cN", "email": "%cE", "date": "%cd" }
|
||||
},`
|
||||
export const git_log = async (
|
||||
from: string | undefined,
|
||||
to = 'HEAD',
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
): Promise<any[]> => {
|
||||
// https://git-scm.com/docs/pretty-formats
|
||||
const r = await Bun.spawn([
|
||||
'git',
|
||||
'--no-pager',
|
||||
'log',
|
||||
`${from ? `${from}...` : ''}${to}`,
|
||||
GITFORMAT,
|
||||
//'--name-status',
|
||||
'--date=iso',
|
||||
])
|
||||
const text = await new Response(r.stdout).text()
|
||||
console.log(text)
|
||||
r /* eturn text
|
||||
.split('----\n')
|
||||
.splice(1)
|
||||
.map((line) => {
|
||||
const [firstLine, , ..._body] = line.split('\n')
|
||||
const [message, shortHash, authorName, date, authorEmail] =
|
||||
firstLine.split('|')
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
const r: any = {
|
||||
date,
|
||||
message,
|
||||
shortHash,
|
||||
author: { name: authorName, email: authorEmail },
|
||||
body: _body.join('\n'),
|
||||
}
|
||||
return r
|
||||
}) */
|
||||
}
|
27
apps/cli/tsconfig.json
Normal file
27
apps/cli/tsconfig.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Enable latest features
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
28
bruno/Changelog/Commit/Create.bru
Normal file
28
bruno/Changelog/Commit/Create.bru
Normal file
@ -0,0 +1,28 @@
|
||||
meta {
|
||||
name: Create
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{API_URL}}/v1/changelog/commit
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:json {
|
||||
[
|
||||
{
|
||||
"changelogId": "aad2c981-e1cc-4de0-8185-8d1c117886b9",
|
||||
"commit": "abc123",
|
||||
"parent": "abc122",
|
||||
"subject": "some",
|
||||
"author": {
|
||||
"name": "asd",
|
||||
"email": "hello@hashdot.co",
|
||||
"date": "somedate"
|
||||
},
|
||||
"body": ""
|
||||
}
|
||||
]
|
||||
}
|
5
bruno/bruno.json
Normal file
5
bruno/bruno.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "boring.tools",
|
||||
"type": "collection"
|
||||
}
|
3
bruno/environments/Development.bru
Normal file
3
bruno/environments/Development.bru
Normal file
@ -0,0 +1,3 @@
|
||||
vars {
|
||||
API_URL: http://localhost:3000
|
||||
}
|
@ -105,13 +105,24 @@ export const changelog_commit = pgTable(
|
||||
onDelete: 'cascade',
|
||||
}),
|
||||
|
||||
shortHash: varchar('shortHash', { length: 8 }).notNull(),
|
||||
author: json('author').$type<{ name: string; email: string }>(),
|
||||
commit: varchar('commit', { length: 8 }).notNull(),
|
||||
parent: varchar('parent', { length: 8 }),
|
||||
subject: text('subject').notNull(),
|
||||
author: json('author').$type<{
|
||||
name: string
|
||||
email: string
|
||||
date: string
|
||||
}>(),
|
||||
commiter: json('comitter').$type<{
|
||||
name: string
|
||||
email: string
|
||||
date: string
|
||||
}>(),
|
||||
|
||||
body: text('body'),
|
||||
message: text('message').notNull(),
|
||||
},
|
||||
(table) => ({
|
||||
unique: uniqueIndex('unique').on(table.changelogId, table.shortHash),
|
||||
unique: uniqueIndex('unique').on(table.changelogId, table.commit),
|
||||
}),
|
||||
)
|
||||
|
||||
|
30
packages/schema/src/commit/base.ts
Normal file
30
packages/schema/src/commit/base.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
export const CommitOutput = z
|
||||
.object({
|
||||
id: z.string().uuid().openapi({
|
||||
example: '9f00f912-f687-42ef-84d7-efde48ca11ef',
|
||||
}),
|
||||
changelogId: z.string().uuid().openapi({
|
||||
example: '8f00f912-f687-42ef-84d7-efde48ca11ef',
|
||||
}),
|
||||
commit: z.string().openapi({
|
||||
example: 'abc123',
|
||||
}),
|
||||
parent: z.string().optional().openapi({
|
||||
example: 'abc122',
|
||||
}),
|
||||
subject: z.string(),
|
||||
author: z.object({
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
date: z.string(),
|
||||
}),
|
||||
commiter: z.object({
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
date: z.string(),
|
||||
}),
|
||||
body: z.string().optional(),
|
||||
})
|
||||
.openapi('Commit')
|
14
packages/schema/src/commit/byId.ts
Normal file
14
packages/schema/src/commit/byId.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
export const VersionByIdParams = z.object({
|
||||
id: z
|
||||
.string()
|
||||
.uuid()
|
||||
.openapi({
|
||||
param: {
|
||||
name: 'id',
|
||||
in: 'path',
|
||||
},
|
||||
example: 'a5ed5965-0506-44e6-aaec-0465ff9fe092',
|
||||
}),
|
||||
})
|
34
packages/schema/src/commit/create.ts
Normal file
34
packages/schema/src/commit/create.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { z } from '@hono/zod-openapi'
|
||||
import { CommitOutput } from './base'
|
||||
|
||||
export const CommitCreateOutput = CommitOutput
|
||||
export const CommitCreateInput = z
|
||||
.array(
|
||||
z.object({
|
||||
changelogId: z.string().uuid().openapi({
|
||||
example: '8f00f912-f687-42ef-84d7-efde48ca11ef',
|
||||
}),
|
||||
commit: z.string().openapi({
|
||||
example: 'abc123',
|
||||
}),
|
||||
parent: z.string().optional().openapi({
|
||||
example: 'abc122',
|
||||
}),
|
||||
subject: z.string(),
|
||||
author: z.object({
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
date: z.string(),
|
||||
}),
|
||||
commiter: z.object({
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
date: z.string(),
|
||||
}),
|
||||
body: z.string().optional(),
|
||||
}),
|
||||
)
|
||||
|
||||
.openapi({
|
||||
required: ['changelogId', 'version', 'markdown', 'releasedAt'],
|
||||
})
|
5
packages/schema/src/commit/index.ts
Normal file
5
packages/schema/src/commit/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './base'
|
||||
//export * from './byId'
|
||||
export * from './create'
|
||||
//export * from './list'
|
||||
//export * from './update'
|
4
packages/schema/src/commit/list.ts
Normal file
4
packages/schema/src/commit/list.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { z } from '@hono/zod-openapi'
|
||||
import { VersionOutput } from './base'
|
||||
|
||||
export const VersionListOutput = z.array(VersionOutput)
|
21
packages/schema/src/commit/update.ts
Normal file
21
packages/schema/src/commit/update.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { z } from '@hono/zod-openapi'
|
||||
import { VersionOutput } from './base'
|
||||
|
||||
export const VersionUpdateOutput = VersionOutput
|
||||
export const VersionUpdateInput = z
|
||||
.object({
|
||||
markdown: z.string().optional(),
|
||||
status: z
|
||||
.enum(['draft', 'review', 'published'])
|
||||
.default('draft')
|
||||
.optional(),
|
||||
releasedAt: z.date().or(z.string()).optional().nullable(),
|
||||
})
|
||||
.openapi({})
|
||||
export const VersionUpdateParams = z
|
||||
.object({
|
||||
id: z.string().uuid(),
|
||||
})
|
||||
.openapi({
|
||||
required: ['id'],
|
||||
})
|
@ -3,3 +3,4 @@ export * from './user'
|
||||
export * from './changelog'
|
||||
export * from './version'
|
||||
export * from './page'
|
||||
export * from './commit'
|
||||
|
Loading…
Reference in New Issue
Block a user