@navios/core 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/docs/README.md +6 -0
  2. package/docs/recipes/prisma.md +60 -0
  3. package/examples/simple-test/api/index.mts +64 -0
  4. package/examples/simple-test/config/config.service.mts +14 -0
  5. package/examples/simple-test/config/configuration.mts +7 -0
  6. package/examples/simple-test/index.mts +16 -0
  7. package/examples/simple-test/src/acl/acl-modern.guard.mts +15 -0
  8. package/examples/simple-test/src/acl/acl.guard.mts +14 -0
  9. package/examples/simple-test/src/acl/app.guard.mts +27 -0
  10. package/examples/simple-test/src/acl/one-more.guard.mts +15 -0
  11. package/examples/simple-test/src/acl/public.attribute.mts +21 -0
  12. package/examples/simple-test/src/app.module.mts +9 -0
  13. package/examples/simple-test/src/user/user.controller.mts +72 -0
  14. package/examples/simple-test/src/user/user.module.mts +14 -0
  15. package/examples/simple-test/src/user/user.service.mts +14 -0
  16. package/{dist → lib}/_tsup-dts-rollup.d.mts +75 -59
  17. package/{dist → lib}/_tsup-dts-rollup.d.ts +75 -59
  18. package/{dist → lib}/index.d.mts +13 -4
  19. package/{dist → lib}/index.d.ts +13 -4
  20. package/{dist → lib}/index.js +270 -490
  21. package/lib/index.js.map +1 -0
  22. package/{dist → lib}/index.mjs +140 -353
  23. package/lib/index.mjs.map +1 -0
  24. package/package.json +12 -13
  25. package/project.json +53 -0
  26. package/src/__tests__/config.service.spec.mts +41 -0
  27. package/src/config/config-service.interface.mts +1 -1
  28. package/src/config/config.provider.mts +23 -47
  29. package/src/config/config.service.mts +25 -8
  30. package/src/decorators/endpoint.decorator.mts +17 -15
  31. package/src/decorators/multipart.decorator.mts +17 -10
  32. package/src/decorators/stream.decorator.mts +17 -10
  33. package/tsconfig.json +16 -0
  34. package/tsup.config.mts +12 -0
  35. package/vitest.config.mts +9 -0
package/docs/README.md ADDED
@@ -0,0 +1,6 @@
1
+ # Introduction
2
+
3
+ Navios us a framework for building Type-Safe Node.js servers. It uses TypeScript and Navios builder to generate a server with a specific structure. The framework is designed to be easy to use and understand, while also being powerful and flexible.
4
+
5
+ Under the hood, Navios makes use of [Fastify](https://www.fastify.io/) for the server implementation, and [Zod](https://zod.dev/) for schema validation. This allows Navios to provide a type-safe experience while still being performant and easy to use.
6
+
@@ -0,0 +1,60 @@
1
+ # Prisma ORM
2
+
3
+ Prisma ORM is a modern database toolkit that simplifies database access and management. It provides a type-safe query builder, migrations, and an intuitive API for working with databases.
4
+
5
+ ## Installation
6
+
7
+ Follow the steps from the [Prisma documentation](https://www.prisma.io/docs/getting-started/quickstart-typescript) to install Prisma in your project.
8
+
9
+ ## Integration
10
+
11
+ The simplest way to integrate Prisma with your project is to create a factory:
12
+
13
+ ```typescript
14
+ import { Injectable, InjectableType, InjectionToken } from '@navios/core'
15
+
16
+ import { PrismaClient } from '@prisma/client'
17
+
18
+ export const PrismaService = InjectionToken.create(PrismaClient)
19
+
20
+ @Injectable({
21
+ token: PrismaService,
22
+ type: InjectableType.Factory,
23
+ })
24
+ export class PrismaServiceFactory {
25
+ async create() {
26
+ const client = new PrismaClient()
27
+ await client.$connect()
28
+ return client
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ You can use the Prisma Service in your application by injecting it into your classes. Here's an example of how to use it in a service:
36
+
37
+ ```typescript
38
+ import { Injectable, syncInject } from '@navios/core'
39
+
40
+ import { PrismaService } from './prisma.service.mjs'
41
+
42
+ @Injectable()
43
+ export class UserService {
44
+ private readonly prisma = syncInject(PrismaService)
45
+
46
+ async getUser(id: string) {
47
+ return this.prisma.user.findUnique({
48
+ where: { id },
49
+ })
50
+ }
51
+
52
+ async createUser(data: { name: string; email: string }) {
53
+ return this.prisma.user.create({
54
+ data,
55
+ })
56
+ }
57
+ }
58
+ ```
59
+
60
+ That's it! You can now use Prisma in your application to interact with your database. You can find more information about Prisma and its features in the [Prisma documentation](https://www.prisma.io/docs/).
@@ -0,0 +1,64 @@
1
+ import { builder } from '@navios/common'
2
+
3
+ import { z } from 'zod'
4
+
5
+ export const authApi = builder({
6
+ useDiscriminatorResponse: true,
7
+ })
8
+
9
+ export const userEndpoint = authApi.declareEndpoint({
10
+ method: 'GET',
11
+ url: '/user',
12
+ responseSchema: z.object({
13
+ id: z.string(),
14
+ name: z.string(),
15
+ email: z.string(),
16
+ }),
17
+ })
18
+
19
+ export const patchUserEndpoint = authApi.declareEndpoint({
20
+ method: 'PATCH',
21
+ url: '/user',
22
+ requestSchema: z.object({
23
+ name: z.string(),
24
+ email: z.string(),
25
+ }),
26
+ responseSchema: z.object({
27
+ id: z.string(),
28
+ name: z.string(),
29
+ email: z.string(),
30
+ }),
31
+ })
32
+
33
+ export const discriminatorEndpoint = authApi.declareEndpoint({
34
+ method: 'GET',
35
+ url: '/discriminator',
36
+ responseSchema: z.discriminatedUnion('success', [
37
+ z.object({
38
+ success: z.literal(true),
39
+ data: z.object({
40
+ id: z.string(),
41
+ name: z.string(),
42
+
43
+ email: z.string(),
44
+ }),
45
+ }),
46
+ z.object({
47
+ success: z.literal(false),
48
+ error: z.object({
49
+ code: z.string(),
50
+ message: z.string(),
51
+ }),
52
+ }),
53
+ ]),
54
+ })
55
+
56
+ export const multipartEndpoint = authApi.declareMultipart({
57
+ method: 'POST',
58
+ url: '/multipart',
59
+ requestSchema: z.object({
60
+ files: z.array(z.instanceof(File)),
61
+ something: z.string(),
62
+ }),
63
+ responseSchema: z.object({}),
64
+ })
@@ -0,0 +1,14 @@
1
+ import type { Path, PathValue } from '../../../src/index.mjs'
2
+
3
+ import { provideConfig } from '../../../src/index.mjs'
4
+ import { configureConfig } from './configuration.mjs'
5
+
6
+ export type ConfigType = ReturnType<typeof configureConfig>
7
+ export type ConfigTypePaths = Path<ConfigType>
8
+ export type ConfigMap = {
9
+ [K in ConfigTypePaths]: PathValue<ConfigType, K>
10
+ }
11
+
12
+ export const ConfigService = provideConfig<ConfigMap>({
13
+ load: configureConfig,
14
+ })
@@ -0,0 +1,7 @@
1
+ import { envInt } from '../../../src/index.mjs'
2
+
3
+ export function configureConfig() {
4
+ return {
5
+ port: envInt('PORT', 4250),
6
+ }
7
+ }
@@ -0,0 +1,16 @@
1
+ import { inject, NaviosFactory } from '../../src/index.mjs'
2
+ import { ConfigService } from './config/config.service.mjs'
3
+ import { AppModule } from './src/app.module.mjs'
4
+
5
+ export async function boot() {
6
+ const app = await NaviosFactory.create(AppModule)
7
+ app.enableCors({
8
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
9
+ })
10
+ app.enableMultipart({})
11
+ await app.init()
12
+ const configService = await inject(ConfigService)
13
+ const port = configService.getOrThrow('port')
14
+ await app.listen({ port: port, host: '0.0.0.0' })
15
+ }
16
+ await boot()
@@ -0,0 +1,15 @@
1
+ import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
2
+
3
+ import { Injectable, Logger, syncInject } from '../../../../src/index.mjs'
4
+
5
+ @Injectable()
6
+ export class AclModernGuard implements CanActivate {
7
+ logger = syncInject(Logger, {
8
+ context: AclModernGuard.name,
9
+ })
10
+
11
+ canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
12
+ this.logger.log('ACL Modern Guard activated')
13
+ return true
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
2
+
3
+ import { Injectable, Logger, syncInject } from '../../../../src/index.mjs'
4
+
5
+ @Injectable()
6
+ export class AclGuard implements CanActivate {
7
+ logger = syncInject(Logger, {
8
+ context: AclGuard.name,
9
+ })
10
+ canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
11
+ this.logger.log('ACL Guard activated')
12
+ return true
13
+ }
14
+ }
@@ -0,0 +1,27 @@
1
+ import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
2
+
3
+ import {
4
+ AttributeFactory,
5
+ Injectable,
6
+ Logger,
7
+ syncInject,
8
+ } from '../../../../src/index.mjs'
9
+ import { Public } from './public.attribute.mjs'
10
+
11
+ @Injectable()
12
+ export class AppGuard implements CanActivate {
13
+ logger = syncInject(Logger, {
14
+ context: AppGuard.name,
15
+ })
16
+
17
+ canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
18
+ const isPublic = AttributeFactory.getLast(Public, [
19
+ executionContext.getModule(),
20
+ executionContext.getController(),
21
+ executionContext.getHandler(),
22
+ ])
23
+ this.logger.log('App Guard activated')
24
+ this.logger.log('isPublic', isPublic)
25
+ return true
26
+ }
27
+ }
@@ -0,0 +1,15 @@
1
+ import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
2
+
3
+ import { Injectable, Logger, syncInject } from '../../../../src/index.mjs'
4
+
5
+ @Injectable()
6
+ export class OneMoreGuard implements CanActivate {
7
+ logger = syncInject(Logger, {
8
+ context: OneMoreGuard.name,
9
+ })
10
+
11
+ canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
12
+ this.logger.log('One More Guard activated')
13
+ return true
14
+ }
15
+ }
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod'
2
+
3
+ import { AttributeFactory } from '../../../../src/index.mjs'
4
+
5
+ export const PublicSymbol = Symbol.for('Public')
6
+
7
+ export const Public = AttributeFactory.createAttribute(PublicSymbol)
8
+ export const RolesSymbol = Symbol.for('Roles')
9
+
10
+ export const RolesSchema = z.object({
11
+ roles: z.array(
12
+ z.union([
13
+ z.literal('VIEWER'),
14
+ z.literal('USER'),
15
+ z.literal('ADMIN'),
16
+ z.literal('OWNER'),
17
+ ]),
18
+ ),
19
+ })
20
+
21
+ export const Roles = AttributeFactory.createAttribute(RolesSymbol, RolesSchema)
@@ -0,0 +1,9 @@
1
+ import { Module } from '../../../src/index.mjs'
2
+ import { AppGuard } from './acl/app.guard.mjs'
3
+ import { UserModule } from './user/user.module.mjs'
4
+
5
+ @Module({
6
+ imports: [UserModule],
7
+ guards: [AppGuard],
8
+ })
9
+ export class AppModule {}
@@ -0,0 +1,72 @@
1
+ import type {
2
+ EndpointParams,
3
+ EndpointResult,
4
+ MultipartParams,
5
+ } from '../../../../src/index.mjs'
6
+
7
+ import {
8
+ Controller,
9
+ Endpoint,
10
+ Logger,
11
+ Multipart,
12
+ syncInject,
13
+ UseGuards,
14
+ } from '../../../../src/index.mjs'
15
+ import {
16
+ discriminatorEndpoint,
17
+ multipartEndpoint,
18
+ patchUserEndpoint,
19
+ userEndpoint,
20
+ } from '../../api/index.mjs'
21
+ import { AclGuard } from '../acl/acl.guard.mjs'
22
+ import { OneMoreGuard } from '../acl/one-more.guard.mjs'
23
+ import { Public } from '../acl/public.attribute.mjs'
24
+ import { UserService } from './user.service.mjs'
25
+
26
+ @UseGuards(AclGuard)
27
+ @Controller()
28
+ export class UserController {
29
+ userService = syncInject(UserService)
30
+ logger = syncInject(Logger, {
31
+ context: UserController.name,
32
+ })
33
+
34
+ @Public()
35
+ @UseGuards(OneMoreGuard)
36
+ @Endpoint(userEndpoint)
37
+ async me(params: EndpointParams<typeof userEndpoint>) {
38
+ this.logger.log(params)
39
+ return this.userService.getUser()
40
+ }
41
+
42
+ @Endpoint(patchUserEndpoint)
43
+ async patchMe(params: EndpointParams<typeof patchUserEndpoint>) {
44
+ this.logger.log(params)
45
+ return {
46
+ ...this.userService.getUser(),
47
+ ...params.data,
48
+ }
49
+ }
50
+
51
+ @Endpoint(discriminatorEndpoint)
52
+ async discriminator(
53
+ params: EndpointParams<typeof discriminatorEndpoint>,
54
+ ): EndpointResult<typeof discriminatorEndpoint> {
55
+ this.logger.log(params)
56
+ return {
57
+ success: true,
58
+ data: {
59
+ id: '123',
60
+ name: 'John Doe',
61
+ email: 'test@example.com',
62
+ },
63
+ }
64
+ }
65
+
66
+ @Multipart(multipartEndpoint)
67
+ async multipart(params: MultipartParams<typeof multipartEndpoint>) {
68
+ this.logger.log(params)
69
+ // params.data.
70
+ return {}
71
+ }
72
+ }
@@ -0,0 +1,14 @@
1
+ import { Logger, Module, syncInject } from '../../../../src/index.mjs'
2
+ import { AclModernGuard } from '../acl/acl-modern.guard.mjs'
3
+ import { UserController } from './user.controller.mjs'
4
+
5
+ @Module({
6
+ controllers: [UserController],
7
+ guards: [AclModernGuard],
8
+ })
9
+ export class UserModule {
10
+ logger = syncInject(Logger)
11
+ onModuleInit() {
12
+ this.logger.debug('Inside UserModule.onModuleInit')
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ import { randomUUID } from 'node:crypto'
2
+
3
+ import { Injectable } from '../../../../src/index.mjs'
4
+
5
+ @Injectable()
6
+ export class UserService {
7
+ getUser() {
8
+ return {
9
+ id: randomUUID() as string,
10
+ name: 'John Doe',
11
+ email: 'test@example.com',
12
+ }
13
+ }
14
+ }