Skip to content

Conversation

@jjnp
Copy link
Contributor

@jjnp jjnp commented Jun 2, 2024

This PR starts adding some groundwork necessary for the endpoints that allow frontend adapters to sync.
Among other minor things, it:

  • Adds endpoints to configure projects via api
  • Adds endpoints to read and write translations for projects
  • add ApiAccess as an entity to the DB (including repo and services) to manage api keys for projects
  • add basic Project repository implementations as they were necessary for the apiAccess

@jjnp jjnp requested a review from mledl as a code owner June 2, 2024 12:31
@jjnp jjnp force-pushed the feature/adapter-api-endpoints branch from 0fc6207 to bb1cdfa Compare June 2, 2024 12:46
@jjnp jjnp force-pushed the feature/adapter-api-endpoints branch from bb1cdfa to 6a45b80 Compare June 2, 2024 12:49
@jjnp jjnp requested a review from benjaminstrasser June 2, 2024 13:03
Copy link
Collaborator

@sjaghori sjaghori left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! 🚀
I got some comments...

"kysely": "^0.27.3",
"pino": "^9.0.0",
"pino-pretty": "^11.0.0",
"uuid": "^9.0.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since node v20 the std. crypto library has builtin uuid v4 generator. Let's not add the dependency here.

import { createTableMigration } from '../migration.util'

export async function up(db: Kysely<unknown>): Promise<void> {
await createTableMigration(db, 'apiaccess')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await createTableMigration(db, 'apiaccess')
await createTableMigration(db, 'api_access')


export async function up(db: Kysely<unknown>): Promise<void> {
await createTableMigration(db, 'apiaccess')
.addColumn('apikey', 'text', (col) => col.unique().notNull())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.addColumn('apikey', 'text', (col) => col.unique().notNull())
.addColumn('api_key', 'text', (col) => col.unique().notNull())

what do you think?

import { z } from 'zod'

const translationKeySchema = z.string().brand('translation-key')
export type TranslationKey = z.infer<typeof translationKeySchema>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to keep this in this folder?

@@ -1 +1 @@
pnpm exec lint-staged
npm test
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also want to run lint-staged no?

}

return validationResult.data
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, we got something similar in production, here is the snippet.
Theoratically the request payload clould be a formdata as well, let's support both json and formdata.

import type { Logger } from 'pino'
import { ZodError, type z } from 'zod'

type ParsedRequestData<T extends z.ZodType> =
	| {
			status: 'success'
			data: z.output<T>
	  }
	| {
			status: 'error'
			data: {
				validationErrorMessage: string
				code: number
			}
	  }

export const parseRequestData = async <T extends z.ZodType>(
	schema: T,
	request: Request,
	logger: Logger,
	kind: 'json' | 'from-data' = 'json'
): Promise<ParsedRequestData<T>> => {
	let parsedPayload: z.output<typeof schema>
	try {
		let payload: unknown
		if (kind === 'json') {
			payload = await request.json()
		} else {
			payload = Object.fromEntries(await request.formData())
		}

		parsedPayload = schema.parse(payload)
	} catch (e: unknown) {
		let validationErrorMessage: string = 'Error parsing request payload.'
		let code = 500
		if (e instanceof ZodError) {
			validationErrorMessage = `Error validating request payload against zod schema. ${e.message}`
			code = 400
			logger.error({
				message: validationErrorMessage,
				name: e.name,
				errors: e.issues
			})
		} else {
			logger.error(validationErrorMessage)
		}

		return { status: 'error', data: { validationErrorMessage, code } }
	}

	return { status: 'success', data: parsedPayload }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants