1.3.0 โ€ข Published 10 months ago

services-framework v1.3.0

Weekly downloads
-
License
MIT
Repository
github
Last release
10 months ago

Linting & Tests

I'd be happy to recieve #feedback moving towards v2

Services Framework, a powerful solution for creating modular, test-driven, and fully typed services for your projects. Say goodbye to messy code and hello to a clean and organized API that enhances developer experience and reusability.

  • ๐Ÿคฉ Modular: Granular and modular control of entities
  • ๐Ÿงช Better testing suites: Write reliable and maintainable code with unit testing / test-driven development
  • ๐Ÿ’ซ Typed: TypeScript support for maximum safety and productivity

Quick Start

Why was Services Framework made?

  • You may re-use the same classes under different contexts: In SvelteKit your frontend and backend code is in the same project. services-framework gives you the ability to re-use classes on the frontend and backend without dragging class embedded functions with. This is helpful if you apply dectorators to validate content.

  • Modularity and re-useability: Write a service once, and re-apply it for multiple classes.

  • Testable: By splitting the code up, you allow for seperation of concerns, giving you more control of test suites.

Usage

// ../entities/user/sign-up.ts
import type { ClassConstructor, StaticServiceFunction, ClassOf } from 'services-framework'
import type { User } from '$entities/user'

// Extending T sets the requirements for T.
export default (<T extends ClassOf<User>>(User: ClassConstructor<T>) => ({

	async signUp(details: Partial<T> & Authentication) {
		const user = new User(...)
		const locals = User.getLocals(user)

		locals.justSignedUp = true
		...
	}

})) satisfies StaticServiceFunction

// Extending T sets the requirements for T. export default (<T extends ClassOf>(User: ClassConstructor, instance: T, locals: Record<any, any>) => ({

async getCompanies() {
	const companies = instance.companies || []
	if(locals.justSignedUp) {
		...
	}
	...
}

})) satisfies InstanceServiceFunction

</details>

<details><summary>databaseHandlers (<i>Service Collection</i>)</summary>

```ts
// ../services/collection.database-handlers.ts
import ... from ...

interface Options = {
	table: string
}

export default <T extends ClassOf<any>>(opts: Options) => ({

	static: {
		locals: {
			table: opts.table,
			...
		},
		services: [
			get<T>
			saveAll<T>
		]
	}

	instance: {
		services: [
			save<T>
		]
	}

}) satisfies Collection<T>
interface Options {...}

export default function(opts: Options) {

	// Custom logic
	...

	// ๐Ÿ‘‡ Do not run code between this function and the returned Record-object
	// As the keys are fetched like this: `service(null, null)`
	return (<T extends ClassOf<any>>(Service: ClassConstructor<T>, instance: T, locals: Record<any, any>) => ({

		async someFunction() {
			...
		}

	})) satisfies InstanceServiceFunction
}

// --- * Usage * ---
const instanceServices = [
	someFunction(...)<Entity>
]
// ../entities/user/index.ts
import signUp from '$entities/user/sign-up'
import logIn from '$entities/user/log-in'
import getCompanies from '$entities/user/get-companies'
import databaseHandlers from '$services/collection.database-handlers'
import passwordHash from '$utils/password-hash.ts'

export class User {
	...
}

export const userService = {
	entity: User,

	static: {
		locals: {
			passwordEncryption: passwordHash
		},
		services: [
			signUp<User>, 
			logIn<User>
		],
	}

	instance: {
		locals: (service, instance) => ({
			justSignedUp: false
		}),
		services: [
			getCompanies<User>
		]
	}

	//*WIP
	collections: [ 
		databaseHandlers<User>({ table: 'users' })
	] 
} satisfies Service<User>
// .../services/index.ts
import { userService } from '$entities/user'
import { companyService } from '$entities/company'

export default createServices({
	User: userService,
	Company: companyService,
	...
})
// .../...
import services from '$serivces'

const { User: UserService } = services
UserService.signUp(...)
useCollection(UserService.locals.collection)
const user = new services.User(...)
user.getCompanies()

const { justSignedUp } = UserService.getLocals(user)
1.3.0

10 months ago

1.2.0

10 months ago

1.1.1

10 months ago

1.0.0-next.0

10 months ago