diff --git a/backend/src/client.js b/backend/src/client.js index a3f1b1b1..54c2a60b 100644 --- a/backend/src/client.js +++ b/backend/src/client.js @@ -1,6 +1,8 @@ // For more information about this file see https://dove.feathersjs.com/guides/cli/client.html import { feathers } from '@feathersjs/feathers' import authenticationClient from '@feathersjs/authentication-client' +import { stripeEventsClient } from './services/stripe-events/stripe-events.shared.js' + import { userEngagementsClient } from './services/user-engagements/user-engagements.shared.js' import { notificationsClient } from './services/notifications/notifications.shared.js' @@ -108,5 +110,7 @@ export const createClient = (connection, authenticationOptions = {}) => { client.configure(publisherClient) + client.configure(stripeEventsClient) + return client } diff --git a/backend/src/services/index.js b/backend/src/services/index.js index 9fc2d46b..21a709f2 100644 --- a/backend/src/services/index.js +++ b/backend/src/services/index.js @@ -1,3 +1,5 @@ +import { stripeEvents } from './stripe-events/stripe-events.js' + import { keywords } from './keywords/keywords.js' import { orgInvites } from './org-invites/org-invites.js' @@ -45,6 +47,8 @@ import { download } from './download/download.js' import { publisher } from './publisher/publisher.js' export const services = (app) => { + app.configure(stripeEvents) + app.configure(orgSecondaryReferences) app.configure(preferences) diff --git a/backend/src/services/stripe-events/stripe-events.class.js b/backend/src/services/stripe-events/stripe-events.class.js new file mode 100644 index 00000000..51c28210 --- /dev/null +++ b/backend/src/services/stripe-events/stripe-events.class.js @@ -0,0 +1,11 @@ +import { MongoDBService } from '@feathersjs/mongodb' + +// By default calls the standard MongoDB adapter service methods but can be customized with your own functionality. +export class StripeEventsService extends MongoDBService {} + +export const getOptions = (app) => { + return { + paginate: app.get('paginate'), + Model: app.get('mongodbClient').then((db) => db.collection('stripe-events')) + } +} diff --git a/backend/src/services/stripe-events/stripe-events.js b/backend/src/services/stripe-events/stripe-events.js new file mode 100644 index 00000000..bf0990d3 --- /dev/null +++ b/backend/src/services/stripe-events/stripe-events.js @@ -0,0 +1,61 @@ +// For more information about this file see https://dove.feathersjs.com/guides/cli/service.html + +import { hooks as schemaHooks } from '@feathersjs/schema' +import { + stripeEventsDataValidator, + stripeEventsPatchValidator, + stripeEventsQueryValidator, + stripeEventsResolver, + stripeEventsExternalResolver, + stripeEventsDataResolver, + stripeEventsPatchResolver, + stripeEventsQueryResolver +} from './stripe-events.schema.js' +import { StripeEventsService, getOptions } from './stripe-events.class.js' +import { stripeEventsPath, stripeEventsMethods } from './stripe-events.shared.js' + +export * from './stripe-events.class.js' +export * from './stripe-events.schema.js' + +// A configure function that registers the service and its hooks via `app.configure` +export const stripeEvents = (app) => { + // Register our service on the Feathers application + app.use(stripeEventsPath, new StripeEventsService(getOptions(app)), { + // A list of all methods this service exposes externally + methods: stripeEventsMethods, + // You can add additional custom events to be sent to clients here + events: [] + }) + // Initialize hooks + app.service(stripeEventsPath).hooks({ + around: { + all: [ + schemaHooks.resolveExternal(stripeEventsExternalResolver), + schemaHooks.resolveResult(stripeEventsResolver) + ] + }, + before: { + all: [ + schemaHooks.validateQuery(stripeEventsQueryValidator), + schemaHooks.resolveQuery(stripeEventsQueryResolver) + ], + find: [], + get: [], + create: [ + schemaHooks.validateData(stripeEventsDataValidator), + schemaHooks.resolveData(stripeEventsDataResolver) + ], + patch: [ + schemaHooks.validateData(stripeEventsPatchValidator), + schemaHooks.resolveData(stripeEventsPatchResolver) + ], + remove: [] + }, + after: { + all: [] + }, + error: { + all: [] + } + }) +} diff --git a/backend/src/services/stripe-events/stripe-events.schema.js b/backend/src/services/stripe-events/stripe-events.schema.js new file mode 100644 index 00000000..f61d8e2a --- /dev/null +++ b/backend/src/services/stripe-events/stripe-events.schema.js @@ -0,0 +1,59 @@ +// // For more information about this file see https://dove.feathersjs.com/guides/cli/service.schemas.html +import { resolve } from '@feathersjs/schema' +import { Type, getValidator, querySyntax } from '@feathersjs/typebox' +import { ObjectIdSchema } from '@feathersjs/typebox' +import { dataValidator, queryValidator } from '../../validators.js' +import {stripeEventsDataSchema, stripeEventsProcessedSchema} from "./stripe-events.subdocs.schema.js"; + + +// Main data model schema +export const stripeEventsSchema = Type.Object( + { + _id: ObjectIdSchema(), // mongodb id + id: Type.String(), // stripe id + object: Type.String(), // "event" + api_version: Type.String(), // "2019-02-19" or similar + created: Type.Integer(), // this is unix timestamp int + data: stripeEventsDataSchema, + processed: stripeEventsProcessedSchema, + }, + { $id: 'StripeEvents', additionalProperties: false } +) +export const stripeEventsValidator = getValidator(stripeEventsSchema, dataValidator) +export const stripeEventsResolver = resolve({}) + +export const stripeEventsExternalResolver = resolve({}) + +// Schema for creating new entries +export const stripeEventsDataSchema = Type.Pick(stripeEventsSchema, [ + // pretty much everything except `processed` and `_id` + 'id', + 'object', + 'api_version', + 'created', + 'data', +], { + $id: 'StripeEventsData' +}) +export const stripeEventsDataValidator = getValidator(stripeEventsDataSchema, dataValidator) +export const stripeEventsDataResolver = resolve({}) + +// Schema for updating existing entries +export const stripeEventsPatchSchema = Type.Partial(stripeEventsSchema, { + $id: 'StripeEventsPatch' +}) +export const stripeEventsPatchValidator = getValidator(stripeEventsPatchSchema, dataValidator) +export const stripeEventsPatchResolver = resolve({}) + +// Schema for allowed query properties +export const stripeEventsQueryProperties = Type.Pick(stripeEventsSchema, ['_id', 'text']) +export const stripeEventsQuerySchema = Type.Intersect( + [ + querySyntax(stripeEventsQueryProperties), + // Add additional query properties here + Type.Object({}, { additionalProperties: false }) + ], + { additionalProperties: false } +) +export const stripeEventsQueryValidator = getValidator(stripeEventsQuerySchema, queryValidator) +export const stripeEventsQueryResolver = resolve({}) diff --git a/backend/src/services/stripe-events/stripe-events.shared.js b/backend/src/services/stripe-events/stripe-events.shared.js new file mode 100644 index 00000000..c1c2f74d --- /dev/null +++ b/backend/src/services/stripe-events/stripe-events.shared.js @@ -0,0 +1,11 @@ +export const stripeEventsPath = 'stripe-events' + +export const stripeEventsMethods = ['find', 'get', 'create', 'patch', 'remove'] + +export const stripeEventsClient = (client) => { + const connection = client.get('connection') + + client.use(stripeEventsPath, connection.service(stripeEventsPath), { + methods: stripeEventsMethods + }) +} diff --git a/backend/src/services/stripe-events/stripe-events.subdocs.schema.js b/backend/src/services/stripe-events/stripe-events.subdocs.schema.js new file mode 100644 index 00000000..911ea384 --- /dev/null +++ b/backend/src/services/stripe-events/stripe-events.subdocs.schema.js @@ -0,0 +1,48 @@ +import {ObjectIdSchema, Type} from "@feathersjs/typebox"; + +export const stripeEventsDataSchema = Type.Object( + { + object: stripeEventsDataObjectSchema, + livemode: Type.Boolean(), + pending_webhooks: Type.Integer(), + request: Type.Any(), + type: Type.String() + } +) + +export const stripeEventsDataObjectSchema = Type.Object( + { + id: Type.String(), // "seti_1NG8Du2eZvKYlo2C9XMqbR0x", + object: Type.String(), // "setup_intent", + application: Type.Any(), + automatic_payment_methods: Type.Any(), // null, + cancellation_reason: Type.String(), // null, + client_secret: Type.String(), + created: Type.Integer(), // datetime + customer: Type.Any(), + description: Type.String(), + flow_directions: Type.Any(), + last_setup_error: Type.Any(), + latest_attempt: Type.Any(), + livemode: Type.Boolean(), + mandate: Type.Any(), + metadata: Type.Any(), + next_action: Type.Any(), + on_behalf_of: Type.Any(), + payment_method: Type.String(), + payment_method_options: Type.Any(), + payment_method_types: Type.Array(), + single_use_mandate: Type.Any(), + status: Type.String(), + usage: Type.String(), + } +) + +export const stripeEventsProcessedSchema = Type.Object( + { + done: Type.Boolean(), + doneAt: Type.Integer(), + detail: Type.String(), + other: Type.Any(), + } +) diff --git a/backend/test/services/stripe-events/stripe-events.test.js b/backend/test/services/stripe-events/stripe-events.test.js new file mode 100644 index 00000000..b0394748 --- /dev/null +++ b/backend/test/services/stripe-events/stripe-events.test.js @@ -0,0 +1,11 @@ +// For more information about this file see https://dove.feathersjs.com/guides/cli/service.test.html +import assert from 'assert' +import { app } from '../../../src/app.js' + +describe('stripe-events service', () => { + it('registered the service', () => { + const service = app.service('stripe-events') + + assert.ok(service, 'Registered the service') + }) +})