Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 70 additions & 7 deletions functions/send-email-link/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import app from '@constructive-io/knative-job-fn';
import type { Request, Response, NextFunction } from 'express';
import { GraphQLClient } from 'graphql-request';
import gql from 'graphql-tag';
import { generate } from '@launchql/mjml';
Expand Down Expand Up @@ -46,6 +47,60 @@ const GetDatabaseInfo = gql`
}
`;

type GetUserResult = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

pretty sure we dont need to define these again here. need to look for defined types.
Maybe see how dashboard does it??

user: {
username: string | null;
displayName: string | null;
profilePicture: string | null;
} | null;
};

type LegalTermsCompany = {
website: string;
nick: string;
name: string;
};

type LegalTermsEmails = {
support: string;
};

type LegalTermsData = {
emails: LegalTermsEmails;
company: LegalTermsCompany;
};

type SiteTheme = {
theme: {
primary: string;
};
};

type SiteDomain = {
subdomain: string | null;
domain: string;
};

type SiteLogo = {
url?: string | null;
} | null;

type DatabaseInfoResult = {
database?:
| {
sites?: {
nodes?: Array<{
domains?: { nodes?: SiteDomain[] };
logo?: SiteLogo;
title?: string;
siteThemes?: { nodes?: SiteTheme[] };
siteModules?: { nodes?: Array<{ data: LegalTermsData }> };
}>;
};
}
| null;
};

type SendEmailParams = {
email_type: 'invite_email' | 'forgot_password' | 'email_verification';
email: string;
Expand All @@ -64,6 +119,10 @@ type GraphQLContext = {
databaseId: string;
};

type SendEmailLinkMissing = { missing: string };
type SendEmailLinkSuccess = { complete: true; dryRun?: true };
export type SendEmailLinkResult = SendEmailLinkMissing | SendEmailLinkSuccess;

const getRequiredEnv = (name: string): string => {
const value = process.env[name];
if (!value) {
Expand Down Expand Up @@ -94,10 +153,10 @@ const createGraphQLClient = (
export const sendEmailLink = async (
params: SendEmailParams,
context: GraphQLContext
) => {
): Promise<SendEmailLinkResult> => {
const { client, meta, databaseId } = context;

const validateForType = (): { missing?: string } | null => {
const validateForType = (): SendEmailLinkMissing | null => {
switch (params.email_type) {
case 'invite_email':
if (!params.invite_token || !params.sender_id) {
Expand Down Expand Up @@ -131,7 +190,7 @@ export const sendEmailLink = async (
return typeValidation;
}

const databaseInfo = await meta.request<any>(GetDatabaseInfo, {
const databaseInfo = await meta.request<DatabaseInfoResult>(GetDatabaseInfo, {
databaseId
});

Expand Down Expand Up @@ -199,7 +258,7 @@ export const sendEmailLink = async (
const scope = Number(params.invite_type) === 2 ? 'org' : 'app';
url.searchParams.append('type', scope);

const inviter = await client.request<any>(GetUser, {
const inviter = await client.request<GetUserResult>(GetUser, {
userId: params.sender_id
});
inviterName = inviter?.user?.displayName;
Expand Down Expand Up @@ -239,7 +298,7 @@ export const sendEmailLink = async (
break;
}
default:
return false;
return { missing: 'email_type' };
}

const link = url.href;
Expand Down Expand Up @@ -295,7 +354,11 @@ export const sendEmailLink = async (
};

// HTTP/Knative entrypoint (used by @constructive-io/knative-job-fn wrapper)
app.post('/', async (req: any, res: any, next: any) => {
type SendEmailLinkRequestBody = Partial<SendEmailParams>;
type SendEmailLinkRequest = Request<{}, SendEmailLinkResult, SendEmailLinkRequestBody>;
type SendEmailLinkResponse = Response<SendEmailLinkResult>;

app.post('/', async (req: SendEmailLinkRequest, res: SendEmailLinkResponse, next: NextFunction) => {
try {
const params = (req.body || {}) as SendEmailParams;

Expand Down Expand Up @@ -329,7 +392,7 @@ export default app;
if (require.main === module) {
const port = Number(process.env.PORT ?? 8080);
// @constructive-io/knative-job-fn exposes a .listen method that delegates to the Express app
(app as any).listen(port, () => {
app.listen(port, () => {
// eslint-disable-next-line no-console
console.log(`[send-email-link] listening on port ${port}`);
});
Expand Down
9 changes: 7 additions & 2 deletions functions/simple-email/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import app from '@constructive-io/knative-job-fn';
import type { Request, Response, NextFunction } from 'express';
import { parseEnvBoolean } from '@pgpmjs/env';
import { send as sendEmail } from '@launchql/postmaster';

Expand Down Expand Up @@ -27,7 +28,11 @@ const getRequiredField = (

const isDryRun = parseEnvBoolean(process.env.SIMPLE_EMAIL_DRY_RUN) ?? false;

app.post('/', async (req: any, res: any, next: any) => {
type SimpleEmailResponseBody = { complete: true };
type SimpleEmailRequest = Request<{}, SimpleEmailResponseBody, Partial<SimpleEmailPayload>>;
type SimpleEmailResponse = Response<SimpleEmailResponseBody>;

app.post('/', async (req: SimpleEmailRequest, res: SimpleEmailResponse, next: NextFunction) => {
try {
const payload = (req.body || {}) as SimpleEmailPayload;

Expand Down Expand Up @@ -92,7 +97,7 @@ export default app;
if (require.main === module) {
const port = Number(process.env.PORT ?? 8080);
// @constructive-io/knative-job-fn exposes a .listen method that delegates to the underlying Express app
(app as any).listen(port, () => {
app.listen(port, () => {
// eslint-disable-next-line no-console
console.log(`[simple-email] listening on port ${port}`);
});
Expand Down
10 changes: 7 additions & 3 deletions jobs/job-pg/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ const end = (pool: Pool): void => {

// Callbacks registered for pool close events can accept arbitrary arguments
// (we forward whatever was passed to `onClose`).
type PoolCloseCallback = (...args: any[]) => Promise<void> | void;
type PoolCloseCallback = (...args: unknown[]) => Promise<void> | void;

class PoolManager {
private pgPool: Pool;
private callbacks: Array<[PoolCloseCallback, any, any[]]>;
private callbacks: Array<[PoolCloseCallback, unknown, unknown[]]>;
private _closed: boolean;

constructor({ pgPool = new Pool(pgPoolConfig) }: { pgPool?: Pool } = {}) {
Expand All @@ -77,7 +77,11 @@ class PoolManager {
});
}

onClose(fn: PoolCloseCallback, context?: any, args: any[] = []): void {
onClose(
fn: PoolCloseCallback,
context?: unknown,
args: unknown[] = []
): void {
this.callbacks.push([fn, context, args]);
}

Expand Down
26 changes: 18 additions & 8 deletions jobs/job-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ import { Logger } from '@pgpmjs/logger';

const log = new Logger('jobs:core');

export type QueryParams = readonly unknown[] | undefined;

export type PgClientLike = {
query<T = any>(text: string, params?: any[]): Promise<{ rows: T[] }>;
query<T = unknown>(
text: string,
params?: QueryParams
): Promise<{ rows: T[] }>;
};

export {
Expand Down Expand Up @@ -72,7 +77,7 @@ export const completeJob = async (
);
};

export const getJob = async <T = any>(
export const getJob = async <T = unknown>(
client: PgClientLike,
{ workerId, supportedTaskNames }: GetJobParams
): Promise<T | null> => {
Expand All @@ -86,7 +91,7 @@ export const getJob = async <T = any>(
return (job as T) ?? null;
};

export const getScheduledJob = async <T = any>(
export const getScheduledJob = async <T = unknown>(
client: PgClientLike,
{ workerId, supportedTaskNames }: GetScheduledJobParams
): Promise<T | null> => {
Expand All @@ -100,10 +105,10 @@ export const getScheduledJob = async <T = any>(
return (job as T) ?? null;
};

export const runScheduledJob = async (
export const runScheduledJob = async <T = unknown>(
client: PgClientLike,
{ jobId }: RunScheduledJobParams
): Promise<any | null> => {
): Promise<T | null> => {
log.info(`runScheduledJob job[${jobId}]`);
try {
const {
Expand All @@ -112,9 +117,14 @@ export const runScheduledJob = async (
`SELECT * FROM "${JOBS_SCHEMA}".run_scheduled_job($1);`,
[jobId]
);
return job ?? null;
} catch (e: any) {
if (e?.message === 'ALREADY_SCHEDULED') {
return (job as T) ?? null;
} catch (e: unknown) {
if (
e &&
typeof e === 'object' &&
'message' in e &&
(e as { message?: unknown }).message === 'ALREADY_SCHEDULED'
) {
return null;
}
throw e;
Expand Down
3 changes: 2 additions & 1 deletion jobs/knative-job-example/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import app from '@constructive-io/knative-job-fn';
import type { Request, Response, NextFunction } from 'express';

app.post('/', async (req: any, res: any, next: any) => {
app.post('/', async (req: Request, res: Response, next: NextFunction) => {
if (req.body.throw) {
next(new Error('THROWN_ERROR'));
} else {
Expand Down
Loading
Loading