Skip to content

Commit 1c51e2a

Browse files
committed
feat: separate current project to libs and node fastify
1 parent 01ab409 commit 1c51e2a

19 files changed

+13431
-0
lines changed

packages/stripe-sync-engine-fastify/package-lock.json

+6,717
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "stripe-sync-engine-fastify",
3+
"version": "0.0.1",
4+
"description": "Stripe sync engine node fastify. Sync your Stripe account to your Postgres database",
5+
"main": "index.js",
6+
"author": "Supabase",
7+
"license": "MIT",
8+
"engines": {
9+
"node": ">= 20.0.0"
10+
},
11+
"dependencies": {
12+
"@stripe-sync-engine/lib": "workspace:^",
13+
"@fastify/autoload": "^5.8.0",
14+
"@fastify/swagger": "^8.14.0",
15+
"@fastify/swagger-ui": "^2.1.0",
16+
"fastify": "^4.25.2",
17+
"dotenv": "^16.3.1",
18+
"p-limit": "^3.1.0",
19+
"pg": "^8.11.3",
20+
"pino": "^8.17.2",
21+
"stripe": "^14.21.0",
22+
"yesql": "^7.0.0"
23+
},
24+
"devDependencies": {
25+
"@types/jest": "^29.5.11",
26+
"@types/node": "^20.11.5",
27+
"@types/pg": "^8.10.9",
28+
"@types/yesql": "^4.1.4",
29+
"@typescript-eslint/eslint-plugin": "^6.19.0",
30+
"@typescript-eslint/parser": "^6.19.0",
31+
"eslint": "^8.56.0",
32+
"eslint-config-prettier": "^9.1.0",
33+
"eslint-plugin-prettier": "^5.1.3",
34+
"jest": "^29.7.0",
35+
"prettier": "^3.2.4",
36+
"ts-jest": "^29.1.1",
37+
"tsx": "^4.7.0",
38+
"typescript": "^5.3.3"
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { FastifyInstance } from 'fastify'
2+
import { syncBackfill, SyncBackfillParams, syncSingleEntity } from '@stripe-sync-engine/lib'
3+
import { verifyApiKey } from '../utils/verifyApiKey'
4+
5+
import Stripe from 'stripe'
6+
7+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
8+
export default async function routes(fastify: FastifyInstance) {
9+
fastify.post('/sync', {
10+
preHandler: [verifyApiKey],
11+
handler: async (request, reply) => {
12+
const { created, object, backfillRelatedEntities } =
13+
(request.body as {
14+
created?: Stripe.RangeQueryParam
15+
object?: string
16+
backfillRelatedEntities?: boolean
17+
}) ?? {}
18+
19+
const params = { created, object, backfillRelatedEntities } as SyncBackfillParams
20+
const result = await syncBackfill(params)
21+
return reply.send({
22+
statusCode: 200,
23+
ts: Date.now(),
24+
...result,
25+
})
26+
},
27+
})
28+
29+
fastify.post<{
30+
Params: {
31+
stripeId: string
32+
}
33+
}>('/sync/single/:stripeId', {
34+
preHandler: [verifyApiKey],
35+
schema: {
36+
params: {
37+
type: 'object',
38+
properties: {
39+
stripeId: { type: 'string' },
40+
},
41+
},
42+
},
43+
handler: async (request, reply) => {
44+
const { stripeId } = request.params
45+
46+
const result = await syncSingleEntity(stripeId)
47+
48+
return reply.send({
49+
statusCode: 200,
50+
ts: Date.now(),
51+
data: result,
52+
})
53+
},
54+
})
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import dotenv from 'dotenv'
2+
3+
type configType = {
4+
/** Postgres database URL including authentication */
5+
DATABASE_URL: string
6+
7+
NODE_ENV: string
8+
9+
/** Database schema name. */
10+
SCHEMA: string
11+
12+
/** Stripe secret key used to authenticate requests to the Stripe API. Defaults to empty string */
13+
STRIPE_SECRET_KEY: string
14+
15+
/** Webhook secret from Stripe to verify the signature of webhook events. */
16+
17+
STRIPE_WEBHOOK_SECRET: string
18+
19+
/** API_KEY is used to authenticate requests to the sync-engine. */
20+
API_KEY: string
21+
22+
/** Stripe API version for the webhooks, defaults to 2020-08-27 */
23+
STRIPE_API_VERSION: string
24+
25+
/** Port number the API is running on, defaults to 8080 */
26+
PORT: number
27+
28+
/**
29+
30+
* Stripe limits related lists like invoice items in an invoice to 10 by default.
31+
32+
* By enabling this, sync-engine automatically fetches the remaining elements before saving
33+
* */
34+
AUTO_EXPAND_LISTS: boolean
35+
}
36+
37+
function getConfigFromEnv(key: string, defaultValue?: string): string {
38+
const value = process.env[key]
39+
if (!value && defaultValue === undefined) {
40+
throw new Error(`${key} is undefined`)
41+
}
42+
return value || defaultValue!
43+
}
44+
45+
export function getConfig(): configType {
46+
dotenv.config()
47+
48+
return {
49+
DATABASE_URL: getConfigFromEnv('DATABASE_URL'),
50+
SCHEMA: getConfigFromEnv('SCHEMA', 'stripe'),
51+
NODE_ENV: getConfigFromEnv('NODE_ENV'),
52+
STRIPE_SECRET_KEY: getConfigFromEnv('STRIPE_SECRET_KEY', ''),
53+
STRIPE_WEBHOOK_SECRET: getConfigFromEnv('STRIPE_WEBHOOK_SECRET'),
54+
API_KEY: getConfigFromEnv('API_KEY', 'false'),
55+
STRIPE_API_VERSION: getConfigFromEnv('STRIPE_API_VERSION', '2020-08-27'),
56+
PORT: Number(getConfigFromEnv('PORT', '8080')),
57+
AUTO_EXPAND_LISTS: getConfigFromEnv('AUTO_EXPAND_LISTS', 'false') === 'true',
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from 'fastify'
2+
import { getConfig } from './config'
3+
4+
const config = getConfig()
5+
6+
export const verifyApiKey = (
7+
request: FastifyRequest,
8+
reply: FastifyReply,
9+
done: HookHandlerDoneFunction
10+
): unknown => {
11+
if (!request.headers || !request.headers.authorization) {
12+
return reply.code(401).send('Unauthorized')
13+
}
14+
const { authorization } = request.headers
15+
if (authorization !== config.API_KEY) {
16+
return reply.code(401).send('Unauthorized')
17+
}
18+
done()
19+
}

0 commit comments

Comments
 (0)