@m5kdev/backend 0.8.11 → 0.9.1
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.
- package/dist/src/modules/auth/auth.lib.d.cts +1 -1
- package/dist/src/modules/auth/auth.lib.d.mts +1 -1
- package/dist/src/modules/base/base.procedure.cjs +30 -0
- package/dist/src/modules/base/base.procedure.cjs.map +1 -1
- package/dist/src/modules/base/base.procedure.d.cts +14 -1
- package/dist/src/modules/base/base.procedure.d.mts +14 -1
- package/dist/src/modules/base/base.procedure.mjs +30 -0
- package/dist/src/modules/base/base.procedure.mjs.map +1 -1
- package/dist/src/modules/base/base.service.cjs.map +1 -1
- package/dist/src/modules/base/base.service.d.cts +2 -2
- package/dist/src/modules/base/base.service.d.mts +2 -2
- package/dist/src/modules/base/base.service.mjs.map +1 -1
- package/dist/src/modules/billing/billing.router.cjs +1 -1
- package/dist/src/modules/billing/billing.router.mjs +1 -1
- package/dist/src/modules/connect/connect.dto.d.cts +2 -2
- package/dist/src/modules/connect/connect.dto.d.mts +2 -2
- package/dist/src/modules/connect/connect.repository.d.cts +1 -1
- package/dist/src/modules/connect/connect.repository.d.mts +1 -1
- package/dist/src/modules/connect/connect.service.d.cts +2 -2
- package/dist/src/modules/connect/connect.service.d.mts +2 -2
- package/dist/src/modules/connect/connect.trpc.d.cts +1 -1
- package/dist/src/modules/connect/connect.trpc.d.mts +1 -1
- package/dist/src/modules/docx/docx.service.cjs +21 -0
- package/dist/src/modules/docx/docx.service.cjs.map +1 -0
- package/dist/src/modules/docx/docx.service.d.cts +10 -0
- package/dist/src/modules/docx/docx.service.d.mts +10 -0
- package/dist/src/modules/docx/docx.service.mjs +17 -0
- package/dist/src/modules/docx/docx.service.mjs.map +1 -0
- package/dist/src/modules/file/file.router.cjs +2 -2
- package/dist/src/modules/file/file.router.mjs +1 -1
- package/dist/src/modules/recurrence/recurrence.service.d.cts +2 -2
- package/dist/src/modules/recurrence/recurrence.service.d.mts +2 -2
- package/dist/src/modules/recurrence/recurrence.trpc.d.cts +3 -3
- package/dist/src/modules/recurrence/recurrence.trpc.d.mts +3 -3
- package/dist/src/modules/tag/tag.trpc.d.cts +2 -2
- package/dist/src/modules/tag/tag.trpc.d.mts +2 -2
- package/dist/src/modules/webhook/webhook.router.cjs +1 -1
- package/dist/src/modules/webhook/webhook.router.mjs +1 -1
- package/package.json +8 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.procedure.mjs","names":[],"sources":["../../../../src/modules/base/base.procedure.ts"],"sourcesContent":["import type { QueryInput } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport type { TRPC_ERROR_CODE_KEY } from \"@trpc/server\";\r\nimport { ok } from \"neverthrow\";\r\nimport type { ServerError } from \"../../utils/errors\";\r\nimport type { logger } from \"../../utils/logger\";\r\nimport type { Base } from \"./base.abstract\";\r\nimport { type Actor, type ActorScope, type AuthenticatedActor, validateActor } from \"./base.actor\";\r\nimport type { ServerResult, ServerResultAsync } from \"./base.dto\";\r\nimport type { Entity, ResourceActionGrant } from \"./base.grants\";\r\n\r\ntype ServiceLogger = ReturnType<typeof logger.child>;\r\ntype RepositoryMap = Record<string, Base>;\r\ntype ServiceMap = Record<string, Base>;\r\n\r\nexport type ServiceProcedureContext = {\r\n actor?: AuthenticatedActor | null;\r\n} & Record<string, unknown>;\r\n\r\nexport type ServiceProcedureState = Record<string, unknown>;\r\nexport type ServiceProcedureStoredValue<T> = [T] extends [undefined] ? undefined : Awaited<T>;\r\nexport type ServiceProcedureResultLike<T> = T | ServerResult<T> | Promise<T | ServerResult<T>>;\r\nexport type ServiceProcedureContextFilterScope = ActorScope;\r\nexport type ServiceProcedureContextFilteredInput<TInput> = Extract<NonNullable<TInput>, QueryInput>;\r\ntype ServiceProcedureAuthContext<Scope extends ActorScope> = {\r\n actor: Actor[Scope];\r\n};\r\ntype ServiceProcedureRequiredScopeFromFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined,\r\n> = TInclude extends readonly ServiceProcedureContextFilterScope[]\r\n ? \"team\" extends TInclude[number]\r\n ? \"team\"\r\n : \"organization\" extends TInclude[number]\r\n ? \"organization\"\r\n : \"user\"\r\n : \"user\";\r\n\r\nexport type ServiceProcedure<TInput, TCtx extends ServiceProcedureContext, TOutput> = (\r\n input: TInput,\r\n ctx: TCtx\r\n) => ServerResultAsync<TOutput>;\r\n\r\nexport type ServiceProcedureArgs<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n> = {\r\n input: TInput;\r\n ctx: TCtx;\r\n state: State;\r\n repository: Repositories;\r\n service: Services;\r\n logger: ServiceLogger;\r\n};\r\n\r\nexport type ServiceProcedureStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput = undefined,\r\n> = (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n) => ServiceProcedureResultLike<ServiceProcedureStoredValue<TOutput>>;\r\n\r\nexport type ServiceProcedureInputMapper<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TNextInput,\r\n> = (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n) => ServiceProcedureResultLike<ServiceProcedureStoredValue<TNextInput>>;\r\n\r\nexport type ServiceProcedureHandler<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n> = (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n) => ServiceProcedureResultLike<TOutput>;\r\n\r\nexport type ServiceProcedureEntityResolver<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined,\r\n> =\r\n | TEntities\r\n | ((\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n ) => ServiceProcedureResultLike<TEntities>);\r\n\r\ntype ServiceProcedureAccessBaseConfig = {\r\n action: string;\r\n grants?: ResourceActionGrant[];\r\n};\r\n\r\nexport type ServiceProcedureEntityStepName<State extends ServiceProcedureState> = Extract<\r\n {\r\n [Key in keyof State]: State[Key] extends Entity | Entity[] | undefined ? Key : never;\r\n }[keyof State],\r\n string\r\n>;\r\n\r\nexport type ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined = undefined,\r\n> = ServiceProcedureAccessBaseConfig & {\r\n entities?: ServiceProcedureEntityResolver<TInput, TCtx, Repositories, Services, State, TEntities>;\r\n entityStep?: never;\r\n};\r\n\r\nexport type ServiceProcedureAccessStateConfig<\r\n State extends ServiceProcedureState,\r\n StepName extends ServiceProcedureEntityStepName<State>,\r\n> = ServiceProcedureAccessBaseConfig & {\r\n entityStep: StepName;\r\n entities?: never;\r\n};\r\n\r\nexport type ServiceProcedureAccessConfig<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined = undefined,\r\n> =\r\n | ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State, TEntities>\r\n | ServiceProcedureAccessStateConfig<State, ServiceProcedureEntityStepName<State>>;\r\n\r\nexport interface ServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n> {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ): ServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >;\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ): ServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >;\r\n addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(\r\n include?: TInclude\r\n ): ServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >;\r\n requireAuth<Scope extends ActorScope = \"user\">(\r\n scope?: Scope\r\n ): ServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n handle<TOutput>(\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ): ServiceProcedure<TInput, TCtx, TOutput>;\r\n}\r\n\r\nexport interface PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n> extends ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >;\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ): PermissionServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >;\r\n addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(\r\n include?: TInclude\r\n ): PermissionServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >;\r\n requireAuth<Scope extends ActorScope = \"user\">(\r\n scope?: Scope\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n access(\r\n config: ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n access<TEntities extends Entity | Entity[] | undefined>(\r\n config: ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State,\r\n TEntities\r\n >\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: TEntities }\r\n >;\r\n access<StepName extends ServiceProcedureEntityStepName<State>>(\r\n config: ServiceProcedureAccessStateConfig<State, StepName>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: State[StepName] }\r\n >;\r\n}\r\n\r\ntype BaseServiceProcedureHost<Repositories extends RepositoryMap, Services extends ServiceMap> = {\r\n repository: Repositories;\r\n service: Services;\r\n logger: ServiceLogger;\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include?: { user?: boolean; organization?: boolean; team?: boolean },\r\n query?: QueryInput\r\n ): QueryInput;\r\n error(\r\n code: TRPC_ERROR_CODE_KEY,\r\n message?: string,\r\n options?: { cause?: unknown; clientMessage?: string; log?: boolean }\r\n ): ServerResult<never>;\r\n throwableAsync<T>(fn: () => ServerResultAsync<T>): ServerResultAsync<T>;\r\n handleUnknownError(error: unknown): ServerError;\r\n};\r\n\r\ntype PermissionServiceProcedureHost<\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n> = BaseServiceProcedureHost<Repositories, Services> & {\r\n checkPermission<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): boolean;\r\n checkPermissionAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<boolean>;\r\n};\r\n\r\ntype ProcedureStage = \"start\" | \"auth_passed\" | \"access_passed\" | \"forbidden\" | \"success\" | \"error\";\r\n\r\ntype ProcedureRuntimeStep<Repositories extends RepositoryMap, Services extends ServiceMap> = {\r\n stage: \"use\" | \"input\" | \"auth\" | \"access\";\r\n stepName: string;\r\n run: (\r\n args: ServiceProcedureArgs<\r\n unknown,\r\n ServiceProcedureContext,\r\n Repositories,\r\n Services,\r\n ServiceProcedureState\r\n >\r\n ) => Promise<ServerResult<unknown>>;\r\n};\r\n\r\ntype ProcedureBuilderConfig<Repositories extends RepositoryMap, Services extends ServiceMap> = {\r\n name: string;\r\n steps: ProcedureRuntimeStep<Repositories, Services>[];\r\n};\r\n\r\nconst DEFAULT_CONTEXT_FILTER_INCLUDE = [\r\n \"user\",\r\n] as const satisfies readonly ServiceProcedureContextFilterScope[];\r\n\r\nfunction isServerResult<T>(value: unknown): value is ServerResult<T> {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"isErr\" in value &&\r\n typeof (value as { isErr: unknown }).isErr === \"function\" &&\r\n \"isOk\" in value &&\r\n typeof (value as { isOk: unknown }).isOk === \"function\"\r\n );\r\n}\r\n\r\nasync function normalizeProcedureResult<T>(\r\n result: ServiceProcedureResultLike<T>\r\n): Promise<ServerResult<T>> {\r\n const resolved = await result;\r\n return isServerResult<T>(resolved) ? resolved : ok(resolved);\r\n}\r\n\r\nfunction assertUniqueStepName<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n steps: ProcedureRuntimeStep<Repositories, Services>[],\r\n stepName: string\r\n) {\r\n if (steps.some((step) => step.stepName === stepName)) {\r\n throw new Error(`Duplicate service procedure step name: ${stepName}`);\r\n }\r\n}\r\n\r\nfunction hasStepName<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n steps: ProcedureRuntimeStep<Repositories, Services>[],\r\n stepName: string\r\n) {\r\n return steps.some((step) => step.stepName === stepName);\r\n}\r\n\r\nfunction getContextFilterInclude(\r\n include: readonly ServiceProcedureContextFilterScope[] = DEFAULT_CONTEXT_FILTER_INCLUDE\r\n) {\r\n return {\r\n user: include.includes(\"user\"),\r\n organization: include.includes(\"organization\"),\r\n team: include.includes(\"team\"),\r\n };\r\n}\r\n\r\nfunction getFailureStage(code: TRPC_ERROR_CODE_KEY | undefined): ProcedureStage {\r\n return code === \"FORBIDDEN\" || code === \"UNAUTHORIZED\" ? \"forbidden\" : \"error\";\r\n}\r\n\r\nfunction logProcedureStage<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n procedureName: string,\r\n ctx: ServiceProcedureContext,\r\n stage: ProcedureStage,\r\n {\r\n stepName,\r\n durationMs,\r\n errorCode,\r\n }: {\r\n stepName?: string;\r\n durationMs?: number;\r\n errorCode?: TRPC_ERROR_CODE_KEY;\r\n } = {}\r\n) {\r\n host.logger.debug({\r\n procedureName,\r\n stage,\r\n stepName,\r\n durationMs,\r\n errorCode,\r\n hasActor: Boolean(ctx.actor),\r\n });\r\n}\r\n\r\nfunction requireProcedureActor<\r\n Scope extends ActorScope,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n ctx: ServiceProcedureContext,\r\n scope: Scope\r\n): ServerResult<Actor[Scope]> {\r\n if (!ctx.actor) {\r\n return host.error(\"UNAUTHORIZED\", \"Unauthorized\");\r\n }\r\n\r\n if (!validateActor(ctx.actor, scope)) {\r\n return host.error(\"FORBIDDEN\", \"Forbidden\");\r\n }\r\n\r\n return ok(ctx.actor as Actor[Scope]);\r\n}\r\n\r\nfunction createRequireAuthStep<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n scope: ActorScope = \"user\"\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"auth\",\r\n stepName: \"auth\",\r\n run: async ({ ctx }) => {\r\n return requireProcedureActor(host, ctx, scope);\r\n },\r\n };\r\n}\r\n\r\nfunction createUseStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n>(\r\n stepName: string,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"use\",\r\n stepName,\r\n run: async (args) =>\r\n normalizeProcedureResult(\r\n step(args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>)\r\n ),\r\n };\r\n}\r\n\r\nfunction createInputStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TNextInput,\r\n>(\r\n stepName: string,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"input\",\r\n stepName,\r\n run: async (args) =>\r\n normalizeProcedureResult(\r\n step(args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>)\r\n ),\r\n };\r\n}\r\n\r\nfunction createContextFilterStep<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n include?: readonly ServiceProcedureContextFilterScope[]\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n const contextInclude = getContextFilterInclude(include);\r\n const requiredScope: ActorScope = contextInclude.team\r\n ? \"team\"\r\n : contextInclude.organization\r\n ? \"organization\"\r\n : \"user\";\r\n\r\n return {\r\n stage: \"input\",\r\n stepName: \"contextFilter\",\r\n run: async ({ input, ctx }) => {\r\n const actor = requireProcedureActor(host, ctx, requiredScope);\r\n if (actor.isErr()) return actor;\r\n return ok(host.addContextFilter(actor.value, contextInclude, input as QueryInput));\r\n },\r\n };\r\n}\r\n\r\nfunction createAccessStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined,\r\n>(\r\n host: PermissionServiceProcedureHost<Repositories, Services>,\r\n config: ServiceProcedureAccessConfig<TInput, TCtx, Repositories, Services, State, TEntities>\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"access\",\r\n stepName: \"access\",\r\n run: async (args) => {\r\n const typedArgs = args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>;\r\n const actor = requireProcedureActor(host, typedArgs.ctx, \"user\");\r\n if (actor.isErr()) return actor;\r\n\r\n if (\"entityStep\" in config && typeof config.entityStep === \"string\") {\r\n const entities = typedArgs.state[config.entityStep] as TEntities;\r\n const hasPermission = host.checkPermission(\r\n actor.value,\r\n config.action,\r\n entities as Entity | Entity[] | undefined,\r\n config.grants\r\n );\r\n\r\n if (!hasPermission) {\r\n return host.error(\"FORBIDDEN\");\r\n }\r\n\r\n return ok(entities);\r\n }\r\n\r\n if (typeof config.entities === \"function\") {\r\n const resolveEntities = config.entities as (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n ) => ServiceProcedureResultLike<TEntities>;\r\n\r\n let loadedEntities: TEntities | undefined;\r\n const permission = await host.checkPermissionAsync(\r\n actor.value,\r\n config.action,\r\n async () => {\r\n const entityResult = await normalizeProcedureResult(resolveEntities(typedArgs));\r\n if (entityResult.isOk()) {\r\n loadedEntities = entityResult.value;\r\n }\r\n return entityResult;\r\n },\r\n config.grants\r\n );\r\n\r\n if (permission.isErr()) {\r\n return permission;\r\n }\r\n\r\n if (!permission.value) {\r\n return host.error(\"FORBIDDEN\");\r\n }\r\n\r\n return ok(loadedEntities);\r\n }\r\n\r\n const entities = config.entities;\r\n const hasPermission = host.checkPermission(\r\n actor.value,\r\n config.action,\r\n entities,\r\n config.grants\r\n );\r\n\r\n if (!hasPermission) {\r\n return host.error(\"FORBIDDEN\");\r\n }\r\n\r\n return ok(entities);\r\n },\r\n };\r\n}\r\n\r\nfunction createProcedureHandler<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n config: ProcedureBuilderConfig<Repositories, Services>,\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n): ServiceProcedure<TInput, TCtx, TOutput> {\r\n return async (input, ctx) =>\r\n host.throwableAsync(async () => {\r\n const state: ServiceProcedureState = {};\r\n const startTime = Date.now();\r\n const typedCtx = ctx as ServiceProcedureContext;\r\n let currentInput: unknown = input;\r\n\r\n logProcedureStage(host, config.name, typedCtx, \"start\");\r\n\r\n try {\r\n for (const step of config.steps) {\r\n const stepResult = await step.run({\r\n input: currentInput,\r\n ctx: typedCtx,\r\n state,\r\n repository: host.repository,\r\n service: host.service,\r\n logger: host.logger,\r\n });\r\n\r\n if (stepResult.isErr()) {\r\n logProcedureStage(host, config.name, typedCtx, getFailureStage(stepResult.error.code), {\r\n stepName: step.stepName,\r\n durationMs: Date.now() - startTime,\r\n errorCode: stepResult.error.code,\r\n });\r\n return stepResult as ServerResult<TOutput>;\r\n }\r\n\r\n state[step.stepName] = stepResult.value;\r\n\r\n if (step.stage === \"input\") {\r\n currentInput = stepResult.value;\r\n }\r\n\r\n if (step.stage === \"auth\") {\r\n logProcedureStage(host, config.name, typedCtx, \"auth_passed\", {\r\n stepName: step.stepName,\r\n });\r\n }\r\n\r\n if (step.stage === \"access\") {\r\n logProcedureStage(host, config.name, typedCtx, \"access_passed\", {\r\n stepName: step.stepName,\r\n });\r\n }\r\n }\r\n\r\n const handlerResult = await normalizeProcedureResult(\r\n handler({\r\n input: currentInput as TInput,\r\n ctx: ctx as TCtx,\r\n state: state as State,\r\n repository: host.repository,\r\n service: host.service,\r\n logger: host.logger,\r\n })\r\n );\r\n\r\n if (handlerResult.isErr()) {\r\n logProcedureStage(\r\n host,\r\n config.name,\r\n typedCtx,\r\n getFailureStage(handlerResult.error.code),\r\n {\r\n durationMs: Date.now() - startTime,\r\n errorCode: handlerResult.error.code,\r\n }\r\n );\r\n return handlerResult;\r\n }\r\n\r\n logProcedureStage(host, config.name, typedCtx, \"success\", {\r\n durationMs: Date.now() - startTime,\r\n });\r\n return handlerResult;\r\n } catch (error) {\r\n const serverError = host.handleUnknownError(error);\r\n logProcedureStage(host, config.name, typedCtx, getFailureStage(serverError.code), {\r\n durationMs: Date.now() - startTime,\r\n errorCode: serverError.code,\r\n });\r\n throw error;\r\n }\r\n });\r\n}\r\n\r\nexport function createServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n config: ProcedureBuilderConfig<Repositories, Services>\r\n): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {\r\n function addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(include?: TInclude) {\r\n const steps = hasStepName(config.steps, \"auth\")\r\n ? config.steps\r\n : [...config.steps, createRequireAuthStep(host, \"user\")];\r\n\r\n assertUniqueStepName(steps, \"contextFilter\");\r\n\r\n return createServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >(host, {\r\n ...config,\r\n steps: [...steps, createContextFilterStep(host, include)],\r\n });\r\n }\r\n\r\n const builder: ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> = {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createUseStep(stepName, step)],\r\n });\r\n },\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createInputStep(stepName, step)],\r\n });\r\n },\r\n addContextFilter,\r\n requireAuth<Scope extends ActorScope = \"user\">(scope?: Scope) {\r\n assertUniqueStepName(config.steps, \"auth\");\r\n return createServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createRequireAuthStep(host, scope ?? \"user\")],\r\n });\r\n },\r\n handle<TOutput>(\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n return createProcedureHandler(host, config, handler);\r\n },\r\n };\r\n\r\n return builder;\r\n}\r\n\r\nexport function createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n>(\r\n host: PermissionServiceProcedureHost<Repositories, Services>,\r\n config: ProcedureBuilderConfig<Repositories, Services>\r\n): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {\r\n function addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(include?: TInclude) {\r\n const steps = hasStepName(config.steps, \"auth\")\r\n ? config.steps\r\n : [...config.steps, createRequireAuthStep(host, \"user\")];\r\n\r\n assertUniqueStepName(steps, \"contextFilter\");\r\n\r\n return createPermissionServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >(host, {\r\n ...config,\r\n steps: [...steps, createContextFilterStep(host, include)],\r\n });\r\n }\r\n\r\n function access(\r\n accessConfig: ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n function access<TEntities extends Entity | Entity[] | undefined>(\r\n accessConfig: ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State,\r\n TEntities\r\n >\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: TEntities }\r\n >;\r\n function access<StepName extends ServiceProcedureEntityStepName<State>>(\r\n accessConfig: ServiceProcedureAccessStateConfig<State, StepName>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: State[StepName] }\r\n >;\r\n function access(\r\n accessConfig:\r\n | ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State,\r\n Entity | Entity[] | undefined\r\n >\r\n | ServiceProcedureAccessStateConfig<State, ServiceProcedureEntityStepName<State>>\r\n ) {\r\n assertUniqueStepName(config.steps, \"access\");\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createAccessStep(host, accessConfig)],\r\n });\r\n }\r\n\r\n const builder: PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> = {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createUseStep(stepName, step)],\r\n });\r\n },\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createPermissionServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createInputStep(stepName, step)],\r\n });\r\n },\r\n addContextFilter,\r\n requireAuth<Scope extends ActorScope = \"user\">(scope?: Scope) {\r\n assertUniqueStepName(config.steps, \"auth\");\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createRequireAuthStep(host, scope ?? \"user\")],\r\n });\r\n },\r\n access,\r\n handle<TOutput>(\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n return createProcedureHandler(host, config, handler);\r\n },\r\n };\r\n\r\n return builder;\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.procedure.mjs","names":[],"sources":["../../../../src/modules/base/base.procedure.ts"],"sourcesContent":["import type { QueryInput } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport type { TRPC_ERROR_CODE_KEY } from \"@trpc/server\";\r\nimport { ok } from \"neverthrow\";\r\nimport type { ServerError } from \"../../utils/errors\";\r\nimport type { logger } from \"../../utils/logger\";\r\nimport type { Base } from \"./base.abstract\";\r\nimport { type Actor, type ActorScope, type AuthenticatedActor, validateActor } from \"./base.actor\";\r\nimport type { ServerResult, ServerResultAsync } from \"./base.dto\";\r\nimport type { Entity, ResourceActionGrant } from \"./base.grants\";\r\n\r\ntype ServiceLogger = ReturnType<typeof logger.child>;\r\ntype RepositoryMap = Record<string, Base>;\r\ntype ServiceMap = Record<string, Base>;\r\n\r\nexport type ServiceProcedureContext = {\r\n actor?: AuthenticatedActor | null;\r\n} & Record<string, unknown>;\r\n\r\nexport type ServiceProcedureState = Record<string, unknown>;\r\nexport type ServiceProcedureStoredValue<T> = [T] extends [undefined] ? undefined : Awaited<T>;\r\n/** Value stored in procedure state after `loadResource` (loader may return null/undefined; state is narrowed). */\r\nexport type ServiceProcedureLoadedResource<TOutput> = NonNullable<\r\n ServiceProcedureStoredValue<TOutput>\r\n>;\r\nexport type ServiceProcedureResultLike<T> = T | ServerResult<T> | Promise<T | ServerResult<T>>;\r\nexport type ServiceProcedureContextFilterScope = ActorScope;\r\nexport type ServiceProcedureContextFilteredInput<TInput> = Extract<NonNullable<TInput>, QueryInput>;\r\ntype ServiceProcedureAuthContext<Scope extends ActorScope> = {\r\n actor: Actor[Scope];\r\n};\r\ntype ServiceProcedureRequiredScopeFromFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined,\r\n> = TInclude extends readonly ServiceProcedureContextFilterScope[]\r\n ? \"team\" extends TInclude[number]\r\n ? \"team\"\r\n : \"organization\" extends TInclude[number]\r\n ? \"organization\"\r\n : \"user\"\r\n : \"user\";\r\n\r\nexport type ServiceProcedure<TInput, TCtx extends ServiceProcedureContext, TOutput> = (\r\n input: TInput,\r\n ctx: TCtx\r\n) => ServerResultAsync<TOutput>;\r\n\r\nexport type ServiceProcedureArgs<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n> = {\r\n input: TInput;\r\n ctx: TCtx;\r\n state: State;\r\n repository: Repositories;\r\n service: Services;\r\n logger: ServiceLogger;\r\n};\r\n\r\nexport type ServiceProcedureStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput = undefined,\r\n> = (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n) => ServiceProcedureResultLike<ServiceProcedureStoredValue<TOutput>>;\r\n\r\nexport type ServiceProcedureInputMapper<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TNextInput,\r\n> = (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n) => ServiceProcedureResultLike<ServiceProcedureStoredValue<TNextInput>>;\r\n\r\nexport type ServiceProcedureHandler<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n> = (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n) => ServiceProcedureResultLike<TOutput>;\r\n\r\nexport type ServiceProcedureEntityResolver<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined,\r\n> =\r\n | TEntities\r\n | ((\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n ) => ServiceProcedureResultLike<TEntities>);\r\n\r\ntype ServiceProcedureAccessBaseConfig = {\r\n action: string;\r\n grants?: ResourceActionGrant[];\r\n};\r\n\r\nexport type ServiceProcedureEntityStepName<State extends ServiceProcedureState> = Extract<\r\n {\r\n [Key in keyof State]: State[Key] extends Entity | Entity[] | undefined ? Key : never;\r\n }[keyof State],\r\n string\r\n>;\r\n\r\nexport type ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined = undefined,\r\n> = ServiceProcedureAccessBaseConfig & {\r\n entities?: ServiceProcedureEntityResolver<TInput, TCtx, Repositories, Services, State, TEntities>;\r\n entityStep?: never;\r\n};\r\n\r\nexport type ServiceProcedureAccessStateConfig<\r\n State extends ServiceProcedureState,\r\n StepName extends ServiceProcedureEntityStepName<State>,\r\n> = ServiceProcedureAccessBaseConfig & {\r\n entityStep: StepName;\r\n entities?: never;\r\n};\r\n\r\nexport type ServiceProcedureAccessConfig<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined = undefined,\r\n> =\r\n | ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State, TEntities>\r\n | ServiceProcedureAccessStateConfig<State, ServiceProcedureEntityStepName<State>>;\r\n\r\nexport interface ServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n> {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ): ServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >;\r\n /**\r\n * Loads a value from a `ServerResult` (or plain value) and stores it under `stepName`.\r\n * Propagates `Err`; if the resolved value is falsy, returns `NOT_FOUND`.\r\n * For valid numeric `0` or empty string, use `.use()` instead of this helper.\r\n */\r\n loadResource<StepName extends string, TOutput>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>,\r\n options?: { notFoundMessage?: string }\r\n ): ServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureLoadedResource<TOutput>>\r\n >;\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ): ServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >;\r\n addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(\r\n include?: TInclude\r\n ): ServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >;\r\n requireAuth<Scope extends ActorScope = \"user\">(\r\n scope?: Scope\r\n ): ServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n handle<TOutput>(\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ): ServiceProcedure<TInput, TCtx, TOutput>;\r\n}\r\n\r\nexport interface PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n> extends ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >;\r\n loadResource<StepName extends string, TOutput>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>,\r\n options?: { notFoundMessage?: string }\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureLoadedResource<TOutput>>\r\n >;\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ): PermissionServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >;\r\n addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(\r\n include?: TInclude\r\n ): PermissionServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >;\r\n requireAuth<Scope extends ActorScope = \"user\">(\r\n scope?: Scope\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n access(\r\n config: ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n access<TEntities extends Entity | Entity[] | undefined>(\r\n config: ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State,\r\n TEntities\r\n >\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: TEntities }\r\n >;\r\n access<StepName extends ServiceProcedureEntityStepName<State>>(\r\n config: ServiceProcedureAccessStateConfig<State, StepName>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: State[StepName] }\r\n >;\r\n}\r\n\r\ntype BaseServiceProcedureHost<Repositories extends RepositoryMap, Services extends ServiceMap> = {\r\n repository: Repositories;\r\n service: Services;\r\n logger: ServiceLogger;\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include?: { user?: boolean; organization?: boolean; team?: boolean },\r\n query?: QueryInput\r\n ): QueryInput;\r\n error(\r\n code: TRPC_ERROR_CODE_KEY,\r\n message?: string,\r\n options?: { cause?: unknown; clientMessage?: string; log?: boolean }\r\n ): ServerResult<never>;\r\n throwableAsync<T>(fn: () => ServerResultAsync<T>): ServerResultAsync<T>;\r\n handleUnknownError(error: unknown): ServerError;\r\n};\r\n\r\ntype PermissionServiceProcedureHost<\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n> = BaseServiceProcedureHost<Repositories, Services> & {\r\n checkPermission<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): boolean;\r\n checkPermissionAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<boolean>;\r\n};\r\n\r\ntype ProcedureStage = \"start\" | \"auth_passed\" | \"access_passed\" | \"forbidden\" | \"success\" | \"error\";\r\n\r\ntype ProcedureRuntimeStep<Repositories extends RepositoryMap, Services extends ServiceMap> = {\r\n stage: \"use\" | \"input\" | \"auth\" | \"access\";\r\n stepName: string;\r\n run: (\r\n args: ServiceProcedureArgs<\r\n unknown,\r\n ServiceProcedureContext,\r\n Repositories,\r\n Services,\r\n ServiceProcedureState\r\n >\r\n ) => Promise<ServerResult<unknown>>;\r\n};\r\n\r\ntype ProcedureBuilderConfig<Repositories extends RepositoryMap, Services extends ServiceMap> = {\r\n name: string;\r\n steps: ProcedureRuntimeStep<Repositories, Services>[];\r\n};\r\n\r\nconst DEFAULT_CONTEXT_FILTER_INCLUDE = [\r\n \"user\",\r\n] as const satisfies readonly ServiceProcedureContextFilterScope[];\r\n\r\nfunction isServerResult<T>(value: unknown): value is ServerResult<T> {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"isErr\" in value &&\r\n typeof (value as { isErr: unknown }).isErr === \"function\" &&\r\n \"isOk\" in value &&\r\n typeof (value as { isOk: unknown }).isOk === \"function\"\r\n );\r\n}\r\n\r\nasync function normalizeProcedureResult<T>(\r\n result: ServiceProcedureResultLike<T>\r\n): Promise<ServerResult<T>> {\r\n const resolved = await result;\r\n return isServerResult<T>(resolved) ? resolved : ok(resolved);\r\n}\r\n\r\nfunction assertUniqueStepName<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n steps: ProcedureRuntimeStep<Repositories, Services>[],\r\n stepName: string\r\n) {\r\n if (steps.some((step) => step.stepName === stepName)) {\r\n throw new Error(`Duplicate service procedure step name: ${stepName}`);\r\n }\r\n}\r\n\r\nfunction hasStepName<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n steps: ProcedureRuntimeStep<Repositories, Services>[],\r\n stepName: string\r\n) {\r\n return steps.some((step) => step.stepName === stepName);\r\n}\r\n\r\nfunction getContextFilterInclude(\r\n include: readonly ServiceProcedureContextFilterScope[] = DEFAULT_CONTEXT_FILTER_INCLUDE\r\n) {\r\n return {\r\n user: include.includes(\"user\"),\r\n organization: include.includes(\"organization\"),\r\n team: include.includes(\"team\"),\r\n };\r\n}\r\n\r\nfunction getFailureStage(code: TRPC_ERROR_CODE_KEY | undefined): ProcedureStage {\r\n return code === \"FORBIDDEN\" || code === \"UNAUTHORIZED\" ? \"forbidden\" : \"error\";\r\n}\r\n\r\nfunction logProcedureStage<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n procedureName: string,\r\n ctx: ServiceProcedureContext,\r\n stage: ProcedureStage,\r\n {\r\n stepName,\r\n durationMs,\r\n errorCode,\r\n }: {\r\n stepName?: string;\r\n durationMs?: number;\r\n errorCode?: TRPC_ERROR_CODE_KEY;\r\n } = {}\r\n) {\r\n host.logger.debug({\r\n procedureName,\r\n stage,\r\n stepName,\r\n durationMs,\r\n errorCode,\r\n hasActor: Boolean(ctx.actor),\r\n });\r\n}\r\n\r\nfunction requireProcedureActor<\r\n Scope extends ActorScope,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n ctx: ServiceProcedureContext,\r\n scope: Scope\r\n): ServerResult<Actor[Scope]> {\r\n if (!ctx.actor) {\r\n return host.error(\"UNAUTHORIZED\", \"Unauthorized\");\r\n }\r\n\r\n if (!validateActor(ctx.actor, scope)) {\r\n return host.error(\"FORBIDDEN\", \"Forbidden\");\r\n }\r\n\r\n return ok(ctx.actor as Actor[Scope]);\r\n}\r\n\r\nfunction createRequireAuthStep<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n scope: ActorScope = \"user\"\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"auth\",\r\n stepName: \"auth\",\r\n run: async ({ ctx }) => {\r\n return requireProcedureActor(host, ctx, scope);\r\n },\r\n };\r\n}\r\n\r\nfunction createUseStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n>(\r\n stepName: string,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"use\",\r\n stepName,\r\n run: async (args) =>\r\n normalizeProcedureResult(\r\n step(args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>)\r\n ),\r\n };\r\n}\r\n\r\nconst DEFAULT_LOAD_RESOURCE_NOT_FOUND_MESSAGE = \"Resource not found\";\r\n\r\nfunction createLoadResourceStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n stepName: string,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>,\r\n notFoundMessage: string\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"use\",\r\n stepName,\r\n run: async (args) => {\r\n const normalized = await normalizeProcedureResult(\r\n step(args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>)\r\n );\r\n if (normalized.isErr()) {\r\n return normalized;\r\n }\r\n const value = normalized.value;\r\n if (!value) {\r\n return host.error(\"NOT_FOUND\", notFoundMessage);\r\n }\r\n return ok(value as ServiceProcedureLoadedResource<TOutput>);\r\n },\r\n };\r\n}\r\n\r\nfunction createInputStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TNextInput,\r\n>(\r\n stepName: string,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"input\",\r\n stepName,\r\n run: async (args) =>\r\n normalizeProcedureResult(\r\n step(args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>)\r\n ),\r\n };\r\n}\r\n\r\nfunction createContextFilterStep<Repositories extends RepositoryMap, Services extends ServiceMap>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n include?: readonly ServiceProcedureContextFilterScope[]\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n const contextInclude = getContextFilterInclude(include);\r\n const requiredScope: ActorScope = contextInclude.team\r\n ? \"team\"\r\n : contextInclude.organization\r\n ? \"organization\"\r\n : \"user\";\r\n\r\n return {\r\n stage: \"input\",\r\n stepName: \"contextFilter\",\r\n run: async ({ input, ctx }) => {\r\n const actor = requireProcedureActor(host, ctx, requiredScope);\r\n if (actor.isErr()) return actor;\r\n return ok(host.addContextFilter(actor.value, contextInclude, input as QueryInput));\r\n },\r\n };\r\n}\r\n\r\nfunction createAccessStep<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TEntities extends Entity | Entity[] | undefined,\r\n>(\r\n host: PermissionServiceProcedureHost<Repositories, Services>,\r\n config: ServiceProcedureAccessConfig<TInput, TCtx, Repositories, Services, State, TEntities>\r\n): ProcedureRuntimeStep<Repositories, Services> {\r\n return {\r\n stage: \"access\",\r\n stepName: \"access\",\r\n run: async (args) => {\r\n const typedArgs = args as ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>;\r\n const actor = requireProcedureActor(host, typedArgs.ctx, \"user\");\r\n if (actor.isErr()) return actor;\r\n\r\n if (\"entityStep\" in config && typeof config.entityStep === \"string\") {\r\n const entities = typedArgs.state[config.entityStep] as TEntities;\r\n const hasPermission = host.checkPermission(\r\n actor.value,\r\n config.action,\r\n entities as Entity | Entity[] | undefined,\r\n config.grants\r\n );\r\n\r\n if (!hasPermission) {\r\n return host.error(\"FORBIDDEN\");\r\n }\r\n\r\n return ok(entities);\r\n }\r\n\r\n if (typeof config.entities === \"function\") {\r\n const resolveEntities = config.entities as (\r\n args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>\r\n ) => ServiceProcedureResultLike<TEntities>;\r\n\r\n let loadedEntities: TEntities | undefined;\r\n const permission = await host.checkPermissionAsync(\r\n actor.value,\r\n config.action,\r\n async () => {\r\n const entityResult = await normalizeProcedureResult(resolveEntities(typedArgs));\r\n if (entityResult.isOk()) {\r\n loadedEntities = entityResult.value;\r\n }\r\n return entityResult;\r\n },\r\n config.grants\r\n );\r\n\r\n if (permission.isErr()) {\r\n return permission;\r\n }\r\n\r\n if (!permission.value) {\r\n return host.error(\"FORBIDDEN\");\r\n }\r\n\r\n return ok(loadedEntities);\r\n }\r\n\r\n const entities = config.entities;\r\n const hasPermission = host.checkPermission(\r\n actor.value,\r\n config.action,\r\n entities,\r\n config.grants\r\n );\r\n\r\n if (!hasPermission) {\r\n return host.error(\"FORBIDDEN\");\r\n }\r\n\r\n return ok(entities);\r\n },\r\n };\r\n}\r\n\r\nfunction createProcedureHandler<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState,\r\n TOutput,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n config: ProcedureBuilderConfig<Repositories, Services>,\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n): ServiceProcedure<TInput, TCtx, TOutput> {\r\n return async (input, ctx) =>\r\n host.throwableAsync(async () => {\r\n const state: ServiceProcedureState = {};\r\n const startTime = Date.now();\r\n const typedCtx = ctx as ServiceProcedureContext;\r\n let currentInput: unknown = input;\r\n\r\n logProcedureStage(host, config.name, typedCtx, \"start\");\r\n\r\n try {\r\n for (const step of config.steps) {\r\n const stepResult = await step.run({\r\n input: currentInput,\r\n ctx: typedCtx,\r\n state,\r\n repository: host.repository,\r\n service: host.service,\r\n logger: host.logger,\r\n });\r\n\r\n if (stepResult.isErr()) {\r\n logProcedureStage(host, config.name, typedCtx, getFailureStage(stepResult.error.code), {\r\n stepName: step.stepName,\r\n durationMs: Date.now() - startTime,\r\n errorCode: stepResult.error.code,\r\n });\r\n return stepResult as ServerResult<TOutput>;\r\n }\r\n\r\n state[step.stepName] = stepResult.value;\r\n\r\n if (step.stage === \"input\") {\r\n currentInput = stepResult.value;\r\n }\r\n\r\n if (step.stage === \"auth\") {\r\n logProcedureStage(host, config.name, typedCtx, \"auth_passed\", {\r\n stepName: step.stepName,\r\n });\r\n }\r\n\r\n if (step.stage === \"access\") {\r\n logProcedureStage(host, config.name, typedCtx, \"access_passed\", {\r\n stepName: step.stepName,\r\n });\r\n }\r\n }\r\n\r\n const handlerResult = await normalizeProcedureResult(\r\n handler({\r\n input: currentInput as TInput,\r\n ctx: ctx as TCtx,\r\n state: state as State,\r\n repository: host.repository,\r\n service: host.service,\r\n logger: host.logger,\r\n })\r\n );\r\n\r\n if (handlerResult.isErr()) {\r\n logProcedureStage(\r\n host,\r\n config.name,\r\n typedCtx,\r\n getFailureStage(handlerResult.error.code),\r\n {\r\n durationMs: Date.now() - startTime,\r\n errorCode: handlerResult.error.code,\r\n }\r\n );\r\n return handlerResult;\r\n }\r\n\r\n logProcedureStage(host, config.name, typedCtx, \"success\", {\r\n durationMs: Date.now() - startTime,\r\n });\r\n return handlerResult;\r\n } catch (error) {\r\n const serverError = host.handleUnknownError(error);\r\n logProcedureStage(host, config.name, typedCtx, getFailureStage(serverError.code), {\r\n durationMs: Date.now() - startTime,\r\n errorCode: serverError.code,\r\n });\r\n throw error;\r\n }\r\n });\r\n}\r\n\r\nexport function createServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n>(\r\n host: BaseServiceProcedureHost<Repositories, Services>,\r\n config: ProcedureBuilderConfig<Repositories, Services>\r\n): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {\r\n function addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(include?: TInclude) {\r\n const steps = hasStepName(config.steps, \"auth\")\r\n ? config.steps\r\n : [...config.steps, createRequireAuthStep(host, \"user\")];\r\n\r\n assertUniqueStepName(steps, \"contextFilter\");\r\n\r\n return createServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >(host, {\r\n ...config,\r\n steps: [...steps, createContextFilterStep(host, include)],\r\n });\r\n }\r\n\r\n const builder: ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> = {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createUseStep(stepName, step)],\r\n });\r\n },\r\n loadResource<StepName extends string, TOutput>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>,\r\n options?: { notFoundMessage?: string }\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n const notFoundMessage = options?.notFoundMessage ?? DEFAULT_LOAD_RESOURCE_NOT_FOUND_MESSAGE;\r\n return createServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureLoadedResource<TOutput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createLoadResourceStep(host, stepName, step, notFoundMessage)],\r\n });\r\n },\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createInputStep(stepName, step)],\r\n });\r\n },\r\n addContextFilter,\r\n requireAuth<Scope extends ActorScope = \"user\">(scope?: Scope) {\r\n assertUniqueStepName(config.steps, \"auth\");\r\n return createServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createRequireAuthStep(host, scope ?? \"user\")],\r\n });\r\n },\r\n handle<TOutput>(\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n return createProcedureHandler(host, config, handler);\r\n },\r\n };\r\n\r\n return builder;\r\n}\r\n\r\nexport function createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx extends ServiceProcedureContext,\r\n Repositories extends RepositoryMap,\r\n Services extends ServiceMap,\r\n State extends ServiceProcedureState = Record<string, never>,\r\n>(\r\n host: PermissionServiceProcedureHost<Repositories, Services>,\r\n config: ProcedureBuilderConfig<Repositories, Services>\r\n): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {\r\n function addContextFilter<\r\n TInclude extends readonly ServiceProcedureContextFilterScope[] | undefined = undefined,\r\n >(include?: TInclude) {\r\n const steps = hasStepName(config.steps, \"auth\")\r\n ? config.steps\r\n : [...config.steps, createRequireAuthStep(host, \"user\")];\r\n\r\n assertUniqueStepName(steps, \"contextFilter\");\r\n\r\n return createPermissionServiceProcedureBuilder<\r\n ServiceProcedureContextFilteredInput<TInput>,\r\n TCtx & ServiceProcedureAuthContext<ServiceProcedureRequiredScopeFromFilter<TInclude>>,\r\n Repositories,\r\n Services,\r\n State & { contextFilter: ServiceProcedureContextFilteredInput<TInput> }\r\n >(host, {\r\n ...config,\r\n steps: [...steps, createContextFilterStep(host, include)],\r\n });\r\n }\r\n\r\n function access(\r\n accessConfig: ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State\r\n >;\r\n function access<TEntities extends Entity | Entity[] | undefined>(\r\n accessConfig: ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State,\r\n TEntities\r\n >\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: TEntities }\r\n >;\r\n function access<StepName extends ServiceProcedureEntityStepName<State>>(\r\n accessConfig: ServiceProcedureAccessStateConfig<State, StepName>\r\n ): PermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State & { access: State[StepName] }\r\n >;\r\n function access(\r\n accessConfig:\r\n | ServiceProcedureAccessEntitiesConfig<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State,\r\n Entity | Entity[] | undefined\r\n >\r\n | ServiceProcedureAccessStateConfig<State, ServiceProcedureEntityStepName<State>>\r\n ) {\r\n assertUniqueStepName(config.steps, \"access\");\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<\"user\">,\r\n Repositories,\r\n Services,\r\n State\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createAccessStep(host, accessConfig)],\r\n });\r\n }\r\n\r\n const builder: PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> = {\r\n use<StepName extends string, TOutput = void>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TOutput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createUseStep(stepName, step)],\r\n });\r\n },\r\n loadResource<StepName extends string, TOutput>(\r\n stepName: StepName,\r\n step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>,\r\n options?: { notFoundMessage?: string }\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n const notFoundMessage = options?.notFoundMessage ?? DEFAULT_LOAD_RESOURCE_NOT_FOUND_MESSAGE;\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureLoadedResource<TOutput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createLoadResourceStep(host, stepName, step, notFoundMessage)],\r\n });\r\n },\r\n mapInput<StepName extends string, TNextInput>(\r\n stepName: StepName,\r\n step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>\r\n ) {\r\n assertUniqueStepName(config.steps, stepName);\r\n return createPermissionServiceProcedureBuilder<\r\n ServiceProcedureStoredValue<TNextInput>,\r\n TCtx,\r\n Repositories,\r\n Services,\r\n State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createInputStep(stepName, step)],\r\n });\r\n },\r\n addContextFilter,\r\n requireAuth<Scope extends ActorScope = \"user\">(scope?: Scope) {\r\n assertUniqueStepName(config.steps, \"auth\");\r\n return createPermissionServiceProcedureBuilder<\r\n TInput,\r\n TCtx & ServiceProcedureAuthContext<Scope>,\r\n Repositories,\r\n Services,\r\n State\r\n >(host, {\r\n ...config,\r\n steps: [...config.steps, createRequireAuthStep(host, scope ?? \"user\")],\r\n });\r\n },\r\n access,\r\n handle<TOutput>(\r\n handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>\r\n ) {\r\n return createProcedureHandler(host, config, handler);\r\n },\r\n };\r\n\r\n return builder;\r\n}\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.service.cjs","names":["Base","createServiceProcedureBuilder","validateActor","createPermissionServiceProcedureBuilder","checkPermissionSync","checkPermissionAsync"],"sources":["../../../../src/modules/base/base.service.ts"],"sourcesContent":["import type { QueryFilter, QueryInput } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { err, ok } from \"neverthrow\";\r\nimport { Base } from \"./base.abstract\";\r\nimport { type AuthenticatedActor, validateActor } from \"./base.actor\";\r\nimport type { ServerResult, ServerResultAsync } from \"./base.dto\";\r\nimport {\r\n checkPermissionAsync,\r\n checkPermissionSync,\r\n type Entity,\r\n type ResourceActionGrant,\r\n type ResourceGrant,\r\n} from \"./base.grants\";\r\nimport {\r\n createPermissionServiceProcedureBuilder,\r\n createServiceProcedureBuilder,\r\n type PermissionServiceProcedureBuilder,\r\n type ServiceProcedureBuilder,\r\n type ServiceProcedureContext,\r\n} from \"./base.procedure\";\r\n\r\nexport type {\r\n PermissionServiceProcedureBuilder,\r\n ServiceProcedure,\r\n ServiceProcedureAccessConfig,\r\n ServiceProcedureAccessEntitiesConfig,\r\n ServiceProcedureAccessStateConfig,\r\n ServiceProcedureArgs,\r\n ServiceProcedureBuilder,\r\n ServiceProcedureContext,\r\n ServiceProcedureContextFilteredInput,\r\n ServiceProcedureContextFilterScope,\r\n ServiceProcedureEntityStepName,\r\n ServiceProcedureInputMapper,\r\n} from \"./base.procedure\";\r\n\r\nexport class BaseService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends Base {\r\n constructor(\r\n public repository: Repositories = {} as Repositories,\r\n public service: Services = {} as Services\r\n ) {\r\n super(\"service\");\r\n this.repository = repository;\r\n this.service = service;\r\n }\r\n\r\n addUserFilter(\r\n value: string,\r\n query?: undefined,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): QueryInput;\r\n addUserFilter<TQuery extends QueryInput>(\r\n value: string,\r\n query: TQuery,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): TQuery;\r\n addUserFilter(\r\n value: string,\r\n query?: QueryInput,\r\n columnId = \"userId\",\r\n method: QueryFilter[\"method\"] = \"equals\"\r\n ): QueryInput {\r\n const userFilter: QueryFilter = {\r\n columnId,\r\n type: \"string\",\r\n method,\r\n value,\r\n };\r\n return query\r\n ? { ...query, filters: [...(query?.filters ?? []), userFilter] }\r\n : { filters: [userFilter] };\r\n }\r\n\r\n protected procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include?: { user?: boolean; organization?: boolean; team?: boolean },\r\n query?: undefined,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): QueryInput;\r\n addContextFilter<TQuery extends QueryInput>(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } | undefined,\r\n query: TQuery,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): TQuery;\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } = {\r\n user: true,\r\n organization: false,\r\n team: false,\r\n },\r\n query?: QueryInput,\r\n map: Record<string, { columnId: string; method: QueryFilter[\"method\"] }> = {\r\n userId: {\r\n columnId: \"userId\",\r\n method: \"equals\",\r\n },\r\n organizationId: {\r\n columnId: \"organizationId\",\r\n method: \"equals\",\r\n },\r\n teamId: {\r\n columnId: \"teamId\",\r\n method: \"equals\",\r\n },\r\n }\r\n ): QueryInput {\r\n const filters: QueryFilter[] = [];\r\n\r\n if (include.user) {\r\n filters.push({\r\n columnId: map.userId.columnId,\r\n type: \"string\",\r\n method: map.userId.method,\r\n value: actor.userId,\r\n });\r\n }\r\n if (include.organization) {\r\n if (!validateActor(actor, \"organization\")) {\r\n throw new Error(\"Organization-scoped context filter requires an organization actor\");\r\n }\r\n filters.push({\r\n columnId: map.organizationId.columnId,\r\n type: \"string\",\r\n method: map.organizationId.method,\r\n value: actor.organizationId!,\r\n });\r\n }\r\n if (include.team) {\r\n if (!validateActor(actor, \"team\")) {\r\n throw new Error(\"Team-scoped context filter requires a team actor\");\r\n }\r\n filters.push({\r\n columnId: map.teamId.columnId,\r\n type: \"string\",\r\n method: map.teamId.method,\r\n value: actor.teamId!,\r\n });\r\n }\r\n return query ? { ...query, filters: [...(query?.filters ?? []), ...filters] } : { filters };\r\n }\r\n}\r\n\r\nexport class BasePermissionService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends BaseService<Repositories, Services, DefaultContext> {\r\n grants: ResourceGrant[];\r\n constructor(repository: Repositories, service: Services, grants: ResourceGrant[] = []) {\r\n super(repository, service);\r\n this.grants = grants;\r\n }\r\n\r\n accessGuard<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): ServerResult<true> {\r\n const hasPermission = this.checkPermission(actor, action, entities, grants);\r\n if (!hasPermission) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n async accessGuardAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<true> {\r\n const hasPermission = await this.checkPermissionAsync(actor, action, getEntities, grants);\r\n if (hasPermission.isErr()) return err(hasPermission.error);\r\n if (!hasPermission.value) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n protected override procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createPermissionServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n checkPermission<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): boolean {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n return checkPermissionSync(actor, actionGrants, entities);\r\n }\r\n\r\n async checkPermissionAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<boolean> {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n const permission = await checkPermissionAsync(actor, actionGrants, getEntities);\r\n if (permission.isErr())\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Failed to check permission\", {\r\n cause: permission.error,\r\n });\r\n return ok(permission.value);\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.service.cjs","names":["Base","createServiceProcedureBuilder","validateActor","createPermissionServiceProcedureBuilder","checkPermissionSync","checkPermissionAsync"],"sources":["../../../../src/modules/base/base.service.ts"],"sourcesContent":["import type { QueryFilter, QueryInput } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { err, ok } from \"neverthrow\";\r\nimport { Base } from \"./base.abstract\";\r\nimport { type AuthenticatedActor, validateActor } from \"./base.actor\";\r\nimport type { ServerResult, ServerResultAsync } from \"./base.dto\";\r\nimport {\r\n checkPermissionAsync,\r\n checkPermissionSync,\r\n type Entity,\r\n type ResourceActionGrant,\r\n type ResourceGrant,\r\n} from \"./base.grants\";\r\nimport {\r\n createPermissionServiceProcedureBuilder,\r\n createServiceProcedureBuilder,\r\n type PermissionServiceProcedureBuilder,\r\n type ServiceProcedureBuilder,\r\n type ServiceProcedureContext,\r\n} from \"./base.procedure\";\r\n\r\nexport type {\r\n PermissionServiceProcedureBuilder,\r\n ServiceProcedure,\r\n ServiceProcedureAccessConfig,\r\n ServiceProcedureAccessEntitiesConfig,\r\n ServiceProcedureAccessStateConfig,\r\n ServiceProcedureArgs,\r\n ServiceProcedureBuilder,\r\n ServiceProcedureContext,\r\n ServiceProcedureContextFilteredInput,\r\n ServiceProcedureContextFilterScope,\r\n ServiceProcedureEntityStepName,\r\n ServiceProcedureInputMapper,\r\n ServiceProcedureLoadedResource,\r\n} from \"./base.procedure\";\r\n\r\nexport class BaseService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends Base {\r\n constructor(\r\n public repository: Repositories = {} as Repositories,\r\n public service: Services = {} as Services\r\n ) {\r\n super(\"service\");\r\n this.repository = repository;\r\n this.service = service;\r\n }\r\n\r\n addUserFilter(\r\n value: string,\r\n query?: undefined,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): QueryInput;\r\n addUserFilter<TQuery extends QueryInput>(\r\n value: string,\r\n query: TQuery,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): TQuery;\r\n addUserFilter(\r\n value: string,\r\n query?: QueryInput,\r\n columnId = \"userId\",\r\n method: QueryFilter[\"method\"] = \"equals\"\r\n ): QueryInput {\r\n const userFilter: QueryFilter = {\r\n columnId,\r\n type: \"string\",\r\n method,\r\n value,\r\n };\r\n return query\r\n ? { ...query, filters: [...(query?.filters ?? []), userFilter] }\r\n : { filters: [userFilter] };\r\n }\r\n\r\n protected procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include?: { user?: boolean; organization?: boolean; team?: boolean },\r\n query?: undefined,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): QueryInput;\r\n addContextFilter<TQuery extends QueryInput>(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } | undefined,\r\n query: TQuery,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): TQuery;\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } = {\r\n user: true,\r\n organization: false,\r\n team: false,\r\n },\r\n query?: QueryInput,\r\n map: Record<string, { columnId: string; method: QueryFilter[\"method\"] }> = {\r\n userId: {\r\n columnId: \"userId\",\r\n method: \"equals\",\r\n },\r\n organizationId: {\r\n columnId: \"organizationId\",\r\n method: \"equals\",\r\n },\r\n teamId: {\r\n columnId: \"teamId\",\r\n method: \"equals\",\r\n },\r\n }\r\n ): QueryInput {\r\n const filters: QueryFilter[] = [];\r\n\r\n if (include.user) {\r\n filters.push({\r\n columnId: map.userId.columnId,\r\n type: \"string\",\r\n method: map.userId.method,\r\n value: actor.userId,\r\n });\r\n }\r\n if (include.organization) {\r\n if (!validateActor(actor, \"organization\")) {\r\n throw new Error(\"Organization-scoped context filter requires an organization actor\");\r\n }\r\n filters.push({\r\n columnId: map.organizationId.columnId,\r\n type: \"string\",\r\n method: map.organizationId.method,\r\n value: actor.organizationId!,\r\n });\r\n }\r\n if (include.team) {\r\n if (!validateActor(actor, \"team\")) {\r\n throw new Error(\"Team-scoped context filter requires a team actor\");\r\n }\r\n filters.push({\r\n columnId: map.teamId.columnId,\r\n type: \"string\",\r\n method: map.teamId.method,\r\n value: actor.teamId!,\r\n });\r\n }\r\n return query ? { ...query, filters: [...(query?.filters ?? []), ...filters] } : { filters };\r\n }\r\n}\r\n\r\nexport class BasePermissionService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends BaseService<Repositories, Services, DefaultContext> {\r\n grants: ResourceGrant[];\r\n constructor(repository: Repositories, service: Services, grants: ResourceGrant[] = []) {\r\n super(repository, service);\r\n this.grants = grants;\r\n }\r\n\r\n accessGuard<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): ServerResult<true> {\r\n const hasPermission = this.checkPermission(actor, action, entities, grants);\r\n if (!hasPermission) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n async accessGuardAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<true> {\r\n const hasPermission = await this.checkPermissionAsync(actor, action, getEntities, grants);\r\n if (hasPermission.isErr()) return err(hasPermission.error);\r\n if (!hasPermission.value) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n protected override procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createPermissionServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n checkPermission<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): boolean {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n return checkPermissionSync(actor, actionGrants, entities);\r\n }\r\n\r\n async checkPermissionAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<boolean> {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n const permission = await checkPermissionAsync(actor, actionGrants, getEntities);\r\n if (permission.isErr())\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Failed to check permission\", {\r\n cause: permission.error,\r\n });\r\n return ok(permission.value);\r\n }\r\n}\r\n"],"mappings":";;;;;;;;AAoCA,IAAa,cAAb,cAIUA,uCAAAA,KAAK;CACb,YACE,aAAkC,EAAE,EACpC,UAA2B,EAAE,EAC7B;AACA,QAAM,UAAU;AAHT,OAAA,aAAA;AACA,OAAA,UAAA;AAGP,OAAK,aAAa;AAClB,OAAK,UAAU;;CAejB,cACE,OACA,OACA,WAAW,UACX,SAAgC,UACpB;EACZ,MAAM,aAA0B;GAC9B;GACA,MAAM;GACN;GACA;GACD;AACD,SAAO,QACH;GAAE,GAAG;GAAO,SAAS,CAAC,GAAI,OAAO,WAAW,EAAE,EAAG,WAAW;GAAE,GAC9D,EAAE,SAAS,CAAC,WAAW,EAAE;;CAG/B,UACE,MAC+D;AAC/D,SAAOC,wCAAAA,8BAA8B,MAAM;GAAE;GAAM,OAAO,EAAE;GAAE,CAAC;;CAejE,iBACE,OACA,UAAsE;EACpE,MAAM;EACN,cAAc;EACd,MAAM;EACP,EACD,OACA,MAA2E;EACzE,QAAQ;GACN,UAAU;GACV,QAAQ;GACT;EACD,gBAAgB;GACd,UAAU;GACV,QAAQ;GACT;EACD,QAAQ;GACN,UAAU;GACV,QAAQ;GACT;EACF,EACW;EACZ,MAAM,UAAyB,EAAE;AAEjC,MAAI,QAAQ,KACV,SAAQ,KAAK;GACX,UAAU,IAAI,OAAO;GACrB,MAAM;GACN,QAAQ,IAAI,OAAO;GACnB,OAAO,MAAM;GACd,CAAC;AAEJ,MAAI,QAAQ,cAAc;AACxB,OAAI,CAACC,oCAAAA,cAAc,OAAO,eAAe,CACvC,OAAM,IAAI,MAAM,oEAAoE;AAEtF,WAAQ,KAAK;IACX,UAAU,IAAI,eAAe;IAC7B,MAAM;IACN,QAAQ,IAAI,eAAe;IAC3B,OAAO,MAAM;IACd,CAAC;;AAEJ,MAAI,QAAQ,MAAM;AAChB,OAAI,CAACA,oCAAAA,cAAc,OAAO,OAAO,CAC/B,OAAM,IAAI,MAAM,mDAAmD;AAErE,WAAQ,KAAK;IACX,UAAU,IAAI,OAAO;IACrB,MAAM;IACN,QAAQ,IAAI,OAAO;IACnB,OAAO,MAAM;IACd,CAAC;;AAEJ,SAAO,QAAQ;GAAE,GAAG;GAAO,SAAS,CAAC,GAAI,OAAO,WAAW,EAAE,EAAG,GAAG,QAAQ;GAAE,GAAG,EAAE,SAAS;;;AAI/F,IAAa,wBAAb,cAIU,YAAoD;CAC5D;CACA,YAAY,YAA0B,SAAmB,SAA0B,EAAE,EAAE;AACrF,QAAM,YAAY,QAAQ;AAC1B,OAAK,SAAS;;CAGhB,YACE,OACA,QACA,UACA,QACoB;AAEpB,MAAI,CADkB,KAAK,gBAAgB,OAAO,QAAQ,UAAU,OAAO,CACvD,QAAO,KAAK,MAAM,YAAY;AAClD,UAAA,GAAA,WAAA,IAAU,KAAK;;CAGjB,MAAM,iBACJ,OACA,QACA,aACA,QACyB;EACzB,MAAM,gBAAgB,MAAM,KAAK,qBAAqB,OAAO,QAAQ,aAAa,OAAO;AACzF,MAAI,cAAc,OAAO,CAAE,SAAA,GAAA,WAAA,KAAW,cAAc,MAAM;AAC1D,MAAI,CAAC,cAAc,MAAO,QAAO,KAAK,MAAM,YAAY;AACxD,UAAA,GAAA,WAAA,IAAU,KAAK;;CAGjB,UACE,MACyE;AACzE,SAAOC,wCAAAA,wCAAwC,MAAM;GAAE;GAAM,OAAO,EAAE;GAAE,CAAC;;CAG3E,gBACE,OACA,QACA,UACA,QACS;AAET,SAAOC,qCAAAA,oBAAoB,OADN,UAAU,KAAK,OAAO,QAAQ,UAAU,MAAM,WAAW,OAAO,EACrC,SAAS;;CAG3D,MAAM,qBACJ,OACA,QACA,aACA,QAC4B;EAE5B,MAAM,aAAa,MAAMC,qCAAAA,qBAAqB,OADzB,UAAU,KAAK,OAAO,QAAQ,UAAU,MAAM,WAAW,OAAO,EAClB,YAAY;AAC/E,MAAI,WAAW,OAAO,CACpB,QAAO,KAAK,MAAM,yBAAyB,8BAA8B,EACvE,OAAO,WAAW,OACnB,CAAC;AACJ,UAAA,GAAA,WAAA,IAAU,WAAW,MAAM"}
|
|
@@ -2,7 +2,7 @@ import { ServerResult, ServerResultAsync } from "./base.dto.cjs";
|
|
|
2
2
|
import { Base } from "./base.abstract.cjs";
|
|
3
3
|
import { AuthenticatedActor } from "./base.actor.cjs";
|
|
4
4
|
import { Entity, ResourceActionGrant, ResourceGrant } from "./base.grants.cjs";
|
|
5
|
-
import { PermissionServiceProcedureBuilder, ServiceProcedure, ServiceProcedureAccessConfig, ServiceProcedureAccessEntitiesConfig, ServiceProcedureAccessStateConfig, ServiceProcedureArgs, ServiceProcedureBuilder, ServiceProcedureContext, ServiceProcedureContextFilterScope, ServiceProcedureContextFilteredInput, ServiceProcedureEntityStepName, ServiceProcedureInputMapper } from "./base.procedure.cjs";
|
|
5
|
+
import { PermissionServiceProcedureBuilder, ServiceProcedure, ServiceProcedureAccessConfig, ServiceProcedureAccessEntitiesConfig, ServiceProcedureAccessStateConfig, ServiceProcedureArgs, ServiceProcedureBuilder, ServiceProcedureContext, ServiceProcedureContextFilterScope, ServiceProcedureContextFilteredInput, ServiceProcedureEntityStepName, ServiceProcedureInputMapper, ServiceProcedureLoadedResource } from "./base.procedure.cjs";
|
|
6
6
|
import { QueryFilter, QueryInput } from "@m5kdev/commons/modules/schemas/query.schema";
|
|
7
7
|
|
|
8
8
|
//#region src/modules/base/base.service.d.ts
|
|
@@ -40,5 +40,5 @@ declare class BasePermissionService<Repositories extends Record<string, Base>, S
|
|
|
40
40
|
checkPermissionAsync<T extends Entity>(actor: AuthenticatedActor, action: string, getEntities: () => ServerResultAsync<T | T[] | undefined>, grants?: ResourceActionGrant[]): ServerResultAsync<boolean>;
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
-
export { BasePermissionService, BaseService, type PermissionServiceProcedureBuilder, type ServiceProcedure, type ServiceProcedureAccessConfig, type ServiceProcedureAccessEntitiesConfig, type ServiceProcedureAccessStateConfig, type ServiceProcedureArgs, type ServiceProcedureBuilder, type ServiceProcedureContext, type ServiceProcedureContextFilterScope, type ServiceProcedureContextFilteredInput, type ServiceProcedureEntityStepName, type ServiceProcedureInputMapper };
|
|
43
|
+
export { BasePermissionService, BaseService, type PermissionServiceProcedureBuilder, type ServiceProcedure, type ServiceProcedureAccessConfig, type ServiceProcedureAccessEntitiesConfig, type ServiceProcedureAccessStateConfig, type ServiceProcedureArgs, type ServiceProcedureBuilder, type ServiceProcedureContext, type ServiceProcedureContextFilterScope, type ServiceProcedureContextFilteredInput, type ServiceProcedureEntityStepName, type ServiceProcedureInputMapper, type ServiceProcedureLoadedResource };
|
|
44
44
|
//# sourceMappingURL=base.service.d.cts.map
|
|
@@ -2,7 +2,7 @@ import { ServerResult, ServerResultAsync } from "./base.dto.mjs";
|
|
|
2
2
|
import { Base } from "./base.abstract.mjs";
|
|
3
3
|
import { AuthenticatedActor } from "./base.actor.mjs";
|
|
4
4
|
import { Entity, ResourceActionGrant, ResourceGrant } from "./base.grants.mjs";
|
|
5
|
-
import { PermissionServiceProcedureBuilder, ServiceProcedure, ServiceProcedureAccessConfig, ServiceProcedureAccessEntitiesConfig, ServiceProcedureAccessStateConfig, ServiceProcedureArgs, ServiceProcedureBuilder, ServiceProcedureContext, ServiceProcedureContextFilterScope, ServiceProcedureContextFilteredInput, ServiceProcedureEntityStepName, ServiceProcedureInputMapper } from "./base.procedure.mjs";
|
|
5
|
+
import { PermissionServiceProcedureBuilder, ServiceProcedure, ServiceProcedureAccessConfig, ServiceProcedureAccessEntitiesConfig, ServiceProcedureAccessStateConfig, ServiceProcedureArgs, ServiceProcedureBuilder, ServiceProcedureContext, ServiceProcedureContextFilterScope, ServiceProcedureContextFilteredInput, ServiceProcedureEntityStepName, ServiceProcedureInputMapper, ServiceProcedureLoadedResource } from "./base.procedure.mjs";
|
|
6
6
|
import { QueryFilter, QueryInput } from "@m5kdev/commons/modules/schemas/query.schema";
|
|
7
7
|
|
|
8
8
|
//#region src/modules/base/base.service.d.ts
|
|
@@ -40,5 +40,5 @@ declare class BasePermissionService<Repositories extends Record<string, Base>, S
|
|
|
40
40
|
checkPermissionAsync<T extends Entity>(actor: AuthenticatedActor, action: string, getEntities: () => ServerResultAsync<T | T[] | undefined>, grants?: ResourceActionGrant[]): ServerResultAsync<boolean>;
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
-
export { BasePermissionService, BaseService, type PermissionServiceProcedureBuilder, type ServiceProcedure, type ServiceProcedureAccessConfig, type ServiceProcedureAccessEntitiesConfig, type ServiceProcedureAccessStateConfig, type ServiceProcedureArgs, type ServiceProcedureBuilder, type ServiceProcedureContext, type ServiceProcedureContextFilterScope, type ServiceProcedureContextFilteredInput, type ServiceProcedureEntityStepName, type ServiceProcedureInputMapper };
|
|
43
|
+
export { BasePermissionService, BaseService, type PermissionServiceProcedureBuilder, type ServiceProcedure, type ServiceProcedureAccessConfig, type ServiceProcedureAccessEntitiesConfig, type ServiceProcedureAccessStateConfig, type ServiceProcedureArgs, type ServiceProcedureBuilder, type ServiceProcedureContext, type ServiceProcedureContextFilterScope, type ServiceProcedureContextFilteredInput, type ServiceProcedureEntityStepName, type ServiceProcedureInputMapper, type ServiceProcedureLoadedResource };
|
|
44
44
|
//# sourceMappingURL=base.service.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.service.mjs","names":[],"sources":["../../../../src/modules/base/base.service.ts"],"sourcesContent":["import type { QueryFilter, QueryInput } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { err, ok } from \"neverthrow\";\r\nimport { Base } from \"./base.abstract\";\r\nimport { type AuthenticatedActor, validateActor } from \"./base.actor\";\r\nimport type { ServerResult, ServerResultAsync } from \"./base.dto\";\r\nimport {\r\n checkPermissionAsync,\r\n checkPermissionSync,\r\n type Entity,\r\n type ResourceActionGrant,\r\n type ResourceGrant,\r\n} from \"./base.grants\";\r\nimport {\r\n createPermissionServiceProcedureBuilder,\r\n createServiceProcedureBuilder,\r\n type PermissionServiceProcedureBuilder,\r\n type ServiceProcedureBuilder,\r\n type ServiceProcedureContext,\r\n} from \"./base.procedure\";\r\n\r\nexport type {\r\n PermissionServiceProcedureBuilder,\r\n ServiceProcedure,\r\n ServiceProcedureAccessConfig,\r\n ServiceProcedureAccessEntitiesConfig,\r\n ServiceProcedureAccessStateConfig,\r\n ServiceProcedureArgs,\r\n ServiceProcedureBuilder,\r\n ServiceProcedureContext,\r\n ServiceProcedureContextFilteredInput,\r\n ServiceProcedureContextFilterScope,\r\n ServiceProcedureEntityStepName,\r\n ServiceProcedureInputMapper,\r\n} from \"./base.procedure\";\r\n\r\nexport class BaseService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends Base {\r\n constructor(\r\n public repository: Repositories = {} as Repositories,\r\n public service: Services = {} as Services\r\n ) {\r\n super(\"service\");\r\n this.repository = repository;\r\n this.service = service;\r\n }\r\n\r\n addUserFilter(\r\n value: string,\r\n query?: undefined,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): QueryInput;\r\n addUserFilter<TQuery extends QueryInput>(\r\n value: string,\r\n query: TQuery,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): TQuery;\r\n addUserFilter(\r\n value: string,\r\n query?: QueryInput,\r\n columnId = \"userId\",\r\n method: QueryFilter[\"method\"] = \"equals\"\r\n ): QueryInput {\r\n const userFilter: QueryFilter = {\r\n columnId,\r\n type: \"string\",\r\n method,\r\n value,\r\n };\r\n return query\r\n ? { ...query, filters: [...(query?.filters ?? []), userFilter] }\r\n : { filters: [userFilter] };\r\n }\r\n\r\n protected procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include?: { user?: boolean; organization?: boolean; team?: boolean },\r\n query?: undefined,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): QueryInput;\r\n addContextFilter<TQuery extends QueryInput>(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } | undefined,\r\n query: TQuery,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): TQuery;\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } = {\r\n user: true,\r\n organization: false,\r\n team: false,\r\n },\r\n query?: QueryInput,\r\n map: Record<string, { columnId: string; method: QueryFilter[\"method\"] }> = {\r\n userId: {\r\n columnId: \"userId\",\r\n method: \"equals\",\r\n },\r\n organizationId: {\r\n columnId: \"organizationId\",\r\n method: \"equals\",\r\n },\r\n teamId: {\r\n columnId: \"teamId\",\r\n method: \"equals\",\r\n },\r\n }\r\n ): QueryInput {\r\n const filters: QueryFilter[] = [];\r\n\r\n if (include.user) {\r\n filters.push({\r\n columnId: map.userId.columnId,\r\n type: \"string\",\r\n method: map.userId.method,\r\n value: actor.userId,\r\n });\r\n }\r\n if (include.organization) {\r\n if (!validateActor(actor, \"organization\")) {\r\n throw new Error(\"Organization-scoped context filter requires an organization actor\");\r\n }\r\n filters.push({\r\n columnId: map.organizationId.columnId,\r\n type: \"string\",\r\n method: map.organizationId.method,\r\n value: actor.organizationId!,\r\n });\r\n }\r\n if (include.team) {\r\n if (!validateActor(actor, \"team\")) {\r\n throw new Error(\"Team-scoped context filter requires a team actor\");\r\n }\r\n filters.push({\r\n columnId: map.teamId.columnId,\r\n type: \"string\",\r\n method: map.teamId.method,\r\n value: actor.teamId!,\r\n });\r\n }\r\n return query ? { ...query, filters: [...(query?.filters ?? []), ...filters] } : { filters };\r\n }\r\n}\r\n\r\nexport class BasePermissionService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends BaseService<Repositories, Services, DefaultContext> {\r\n grants: ResourceGrant[];\r\n constructor(repository: Repositories, service: Services, grants: ResourceGrant[] = []) {\r\n super(repository, service);\r\n this.grants = grants;\r\n }\r\n\r\n accessGuard<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): ServerResult<true> {\r\n const hasPermission = this.checkPermission(actor, action, entities, grants);\r\n if (!hasPermission) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n async accessGuardAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<true> {\r\n const hasPermission = await this.checkPermissionAsync(actor, action, getEntities, grants);\r\n if (hasPermission.isErr()) return err(hasPermission.error);\r\n if (!hasPermission.value) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n protected override procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createPermissionServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n checkPermission<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): boolean {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n return checkPermissionSync(actor, actionGrants, entities);\r\n }\r\n\r\n async checkPermissionAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<boolean> {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n const permission = await checkPermissionAsync(actor, actionGrants, getEntities);\r\n if (permission.isErr())\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Failed to check permission\", {\r\n cause: permission.error,\r\n });\r\n return ok(permission.value);\r\n }\r\n}\r\n"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"base.service.mjs","names":[],"sources":["../../../../src/modules/base/base.service.ts"],"sourcesContent":["import type { QueryFilter, QueryInput } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { err, ok } from \"neverthrow\";\r\nimport { Base } from \"./base.abstract\";\r\nimport { type AuthenticatedActor, validateActor } from \"./base.actor\";\r\nimport type { ServerResult, ServerResultAsync } from \"./base.dto\";\r\nimport {\r\n checkPermissionAsync,\r\n checkPermissionSync,\r\n type Entity,\r\n type ResourceActionGrant,\r\n type ResourceGrant,\r\n} from \"./base.grants\";\r\nimport {\r\n createPermissionServiceProcedureBuilder,\r\n createServiceProcedureBuilder,\r\n type PermissionServiceProcedureBuilder,\r\n type ServiceProcedureBuilder,\r\n type ServiceProcedureContext,\r\n} from \"./base.procedure\";\r\n\r\nexport type {\r\n PermissionServiceProcedureBuilder,\r\n ServiceProcedure,\r\n ServiceProcedureAccessConfig,\r\n ServiceProcedureAccessEntitiesConfig,\r\n ServiceProcedureAccessStateConfig,\r\n ServiceProcedureArgs,\r\n ServiceProcedureBuilder,\r\n ServiceProcedureContext,\r\n ServiceProcedureContextFilteredInput,\r\n ServiceProcedureContextFilterScope,\r\n ServiceProcedureEntityStepName,\r\n ServiceProcedureInputMapper,\r\n ServiceProcedureLoadedResource,\r\n} from \"./base.procedure\";\r\n\r\nexport class BaseService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends Base {\r\n constructor(\r\n public repository: Repositories = {} as Repositories,\r\n public service: Services = {} as Services\r\n ) {\r\n super(\"service\");\r\n this.repository = repository;\r\n this.service = service;\r\n }\r\n\r\n addUserFilter(\r\n value: string,\r\n query?: undefined,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): QueryInput;\r\n addUserFilter<TQuery extends QueryInput>(\r\n value: string,\r\n query: TQuery,\r\n columnId?: string,\r\n method?: QueryFilter[\"method\"]\r\n ): TQuery;\r\n addUserFilter(\r\n value: string,\r\n query?: QueryInput,\r\n columnId = \"userId\",\r\n method: QueryFilter[\"method\"] = \"equals\"\r\n ): QueryInput {\r\n const userFilter: QueryFilter = {\r\n columnId,\r\n type: \"string\",\r\n method,\r\n value,\r\n };\r\n return query\r\n ? { ...query, filters: [...(query?.filters ?? []), userFilter] }\r\n : { filters: [userFilter] };\r\n }\r\n\r\n protected procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include?: { user?: boolean; organization?: boolean; team?: boolean },\r\n query?: undefined,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): QueryInput;\r\n addContextFilter<TQuery extends QueryInput>(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } | undefined,\r\n query: TQuery,\r\n map?: Record<string, { columnId: string; method: QueryFilter[\"method\"] }>\r\n ): TQuery;\r\n addContextFilter(\r\n actor: AuthenticatedActor,\r\n include: { user?: boolean; organization?: boolean; team?: boolean } = {\r\n user: true,\r\n organization: false,\r\n team: false,\r\n },\r\n query?: QueryInput,\r\n map: Record<string, { columnId: string; method: QueryFilter[\"method\"] }> = {\r\n userId: {\r\n columnId: \"userId\",\r\n method: \"equals\",\r\n },\r\n organizationId: {\r\n columnId: \"organizationId\",\r\n method: \"equals\",\r\n },\r\n teamId: {\r\n columnId: \"teamId\",\r\n method: \"equals\",\r\n },\r\n }\r\n ): QueryInput {\r\n const filters: QueryFilter[] = [];\r\n\r\n if (include.user) {\r\n filters.push({\r\n columnId: map.userId.columnId,\r\n type: \"string\",\r\n method: map.userId.method,\r\n value: actor.userId,\r\n });\r\n }\r\n if (include.organization) {\r\n if (!validateActor(actor, \"organization\")) {\r\n throw new Error(\"Organization-scoped context filter requires an organization actor\");\r\n }\r\n filters.push({\r\n columnId: map.organizationId.columnId,\r\n type: \"string\",\r\n method: map.organizationId.method,\r\n value: actor.organizationId!,\r\n });\r\n }\r\n if (include.team) {\r\n if (!validateActor(actor, \"team\")) {\r\n throw new Error(\"Team-scoped context filter requires a team actor\");\r\n }\r\n filters.push({\r\n columnId: map.teamId.columnId,\r\n type: \"string\",\r\n method: map.teamId.method,\r\n value: actor.teamId!,\r\n });\r\n }\r\n return query ? { ...query, filters: [...(query?.filters ?? []), ...filters] } : { filters };\r\n }\r\n}\r\n\r\nexport class BasePermissionService<\r\n Repositories extends Record<string, Base>,\r\n Services extends Record<string, Base>,\r\n DefaultContext extends ServiceProcedureContext = ServiceProcedureContext,\r\n> extends BaseService<Repositories, Services, DefaultContext> {\r\n grants: ResourceGrant[];\r\n constructor(repository: Repositories, service: Services, grants: ResourceGrant[] = []) {\r\n super(repository, service);\r\n this.grants = grants;\r\n }\r\n\r\n accessGuard<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): ServerResult<true> {\r\n const hasPermission = this.checkPermission(actor, action, entities, grants);\r\n if (!hasPermission) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n async accessGuardAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<true> {\r\n const hasPermission = await this.checkPermissionAsync(actor, action, getEntities, grants);\r\n if (hasPermission.isErr()) return err(hasPermission.error);\r\n if (!hasPermission.value) return this.error(\"FORBIDDEN\");\r\n return ok(true);\r\n }\r\n\r\n protected override procedure<TInput, TCtx extends ServiceProcedureContext = DefaultContext>(\r\n name: string\r\n ): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services> {\r\n return createPermissionServiceProcedureBuilder(this, { name, steps: [] });\r\n }\r\n\r\n checkPermission<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n entities?: T | T[],\r\n grants?: ResourceActionGrant[]\r\n ): boolean {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n return checkPermissionSync(actor, actionGrants, entities);\r\n }\r\n\r\n async checkPermissionAsync<T extends Entity>(\r\n actor: AuthenticatedActor,\r\n action: string,\r\n getEntities: () => ServerResultAsync<T | T[] | undefined>,\r\n grants?: ResourceActionGrant[]\r\n ): ServerResultAsync<boolean> {\r\n const actionGrants = grants ?? this.grants.filter((grant) => grant.action === action);\r\n const permission = await checkPermissionAsync(actor, actionGrants, getEntities);\r\n if (permission.isErr())\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Failed to check permission\", {\r\n cause: permission.error,\r\n });\r\n return ok(permission.value);\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_runtime = require("../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let express = require("express");
|
|
3
4
|
let body_parser = require("body-parser");
|
|
4
5
|
body_parser = require_runtime.__toESM(body_parser);
|
|
5
|
-
let express = require("express");
|
|
6
6
|
//#region src/modules/billing/billing.router.ts
|
|
7
7
|
function createBillingRouter(authMiddleware, service) {
|
|
8
8
|
const billingRouter = (0, express.Router)();
|
|
@@ -30,7 +30,6 @@ declare const connectSelectOutputSchema: z.ZodObject<{
|
|
|
30
30
|
expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
31
31
|
userId: z.ZodString;
|
|
32
32
|
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
33
|
-
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
33
|
provider: z.ZodString;
|
|
35
34
|
accountType: z.ZodString;
|
|
36
35
|
providerAccountId: z.ZodString;
|
|
@@ -38,6 +37,7 @@ declare const connectSelectOutputSchema: z.ZodObject<{
|
|
|
38
37
|
displayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
39
38
|
avatarUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
39
|
tokenType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
41
41
|
metadataJson: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
42
42
|
revokedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
43
43
|
lastRefreshedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
@@ -54,7 +54,6 @@ declare const connectListOutputSchema: z.ZodArray<z.ZodObject<{
|
|
|
54
54
|
expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
55
55
|
userId: z.ZodString;
|
|
56
56
|
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
57
|
-
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
58
57
|
provider: z.ZodString;
|
|
59
58
|
accountType: z.ZodString;
|
|
60
59
|
providerAccountId: z.ZodString;
|
|
@@ -62,6 +61,7 @@ declare const connectListOutputSchema: z.ZodArray<z.ZodObject<{
|
|
|
62
61
|
displayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
62
|
avatarUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
64
63
|
tokenType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
64
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
65
|
metadataJson: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
66
66
|
revokedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
67
67
|
lastRefreshedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
@@ -30,7 +30,6 @@ declare const connectSelectOutputSchema: z.ZodObject<{
|
|
|
30
30
|
expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
31
31
|
userId: z.ZodString;
|
|
32
32
|
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
33
|
-
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
33
|
provider: z.ZodString;
|
|
35
34
|
accountType: z.ZodString;
|
|
36
35
|
providerAccountId: z.ZodString;
|
|
@@ -38,6 +37,7 @@ declare const connectSelectOutputSchema: z.ZodObject<{
|
|
|
38
37
|
displayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
39
38
|
avatarUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
39
|
tokenType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
41
41
|
metadataJson: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
42
42
|
revokedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
43
43
|
lastRefreshedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
@@ -54,7 +54,6 @@ declare const connectListOutputSchema: z.ZodArray<z.ZodObject<{
|
|
|
54
54
|
expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
55
55
|
userId: z.ZodString;
|
|
56
56
|
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
57
|
-
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
58
57
|
provider: z.ZodString;
|
|
59
58
|
accountType: z.ZodString;
|
|
60
59
|
providerAccountId: z.ZodString;
|
|
@@ -62,6 +61,7 @@ declare const connectListOutputSchema: z.ZodArray<z.ZodObject<{
|
|
|
62
61
|
displayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
62
|
avatarUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
64
63
|
tokenType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
64
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
65
|
metadataJson: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
66
66
|
revokedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
67
67
|
lastRefreshedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
|
|
@@ -401,7 +401,6 @@ declare class ConnectRepository extends BaseTableRepository<Orm, Schema, Record<
|
|
|
401
401
|
accessToken: string;
|
|
402
402
|
refreshToken: string | null;
|
|
403
403
|
scope: string | null;
|
|
404
|
-
parentId: string | null;
|
|
405
404
|
provider: string;
|
|
406
405
|
accountType: string;
|
|
407
406
|
providerAccountId: string;
|
|
@@ -409,6 +408,7 @@ declare class ConnectRepository extends BaseTableRepository<Orm, Schema, Record<
|
|
|
409
408
|
displayName: string | null;
|
|
410
409
|
avatarUrl: string | null;
|
|
411
410
|
tokenType: string | null;
|
|
411
|
+
parentId: string | null;
|
|
412
412
|
metadataJson: unknown;
|
|
413
413
|
revokedAt: Date | null;
|
|
414
414
|
lastRefreshedAt: Date | null;
|
|
@@ -401,7 +401,6 @@ declare class ConnectRepository extends BaseTableRepository<Orm, Schema, Record<
|
|
|
401
401
|
accessToken: string;
|
|
402
402
|
refreshToken: string | null;
|
|
403
403
|
scope: string | null;
|
|
404
|
-
parentId: string | null;
|
|
405
404
|
provider: string;
|
|
406
405
|
accountType: string;
|
|
407
406
|
providerAccountId: string;
|
|
@@ -409,6 +408,7 @@ declare class ConnectRepository extends BaseTableRepository<Orm, Schema, Record<
|
|
|
409
408
|
displayName: string | null;
|
|
410
409
|
avatarUrl: string | null;
|
|
411
410
|
tokenType: string | null;
|
|
411
|
+
parentId: string | null;
|
|
412
412
|
metadataJson: unknown;
|
|
413
413
|
revokedAt: Date | null;
|
|
414
414
|
lastRefreshedAt: Date | null;
|
|
@@ -27,7 +27,6 @@ declare class ConnectService extends BaseService<{
|
|
|
27
27
|
accessToken: string;
|
|
28
28
|
refreshToken: string | null;
|
|
29
29
|
scope: string | null;
|
|
30
|
-
parentId: string | null;
|
|
31
30
|
provider: string;
|
|
32
31
|
accountType: string;
|
|
33
32
|
providerAccountId: string;
|
|
@@ -35,6 +34,7 @@ declare class ConnectService extends BaseService<{
|
|
|
35
34
|
displayName: string | null;
|
|
36
35
|
avatarUrl: string | null;
|
|
37
36
|
tokenType: string | null;
|
|
37
|
+
parentId: string | null;
|
|
38
38
|
metadataJson: unknown;
|
|
39
39
|
revokedAt: Date | null;
|
|
40
40
|
lastRefreshedAt: Date | null;
|
|
@@ -48,7 +48,6 @@ declare class ConnectService extends BaseService<{
|
|
|
48
48
|
accessToken: string;
|
|
49
49
|
refreshToken: string | null;
|
|
50
50
|
scope: string | null;
|
|
51
|
-
parentId: string | null;
|
|
52
51
|
provider: string;
|
|
53
52
|
accountType: string;
|
|
54
53
|
providerAccountId: string;
|
|
@@ -56,6 +55,7 @@ declare class ConnectService extends BaseService<{
|
|
|
56
55
|
displayName: string | null;
|
|
57
56
|
avatarUrl: string | null;
|
|
58
57
|
tokenType: string | null;
|
|
58
|
+
parentId: string | null;
|
|
59
59
|
metadataJson: unknown;
|
|
60
60
|
revokedAt: Date | null;
|
|
61
61
|
lastRefreshedAt: Date | null;
|
|
@@ -27,7 +27,6 @@ declare class ConnectService extends BaseService<{
|
|
|
27
27
|
accessToken: string;
|
|
28
28
|
refreshToken: string | null;
|
|
29
29
|
scope: string | null;
|
|
30
|
-
parentId: string | null;
|
|
31
30
|
provider: string;
|
|
32
31
|
accountType: string;
|
|
33
32
|
providerAccountId: string;
|
|
@@ -35,6 +34,7 @@ declare class ConnectService extends BaseService<{
|
|
|
35
34
|
displayName: string | null;
|
|
36
35
|
avatarUrl: string | null;
|
|
37
36
|
tokenType: string | null;
|
|
37
|
+
parentId: string | null;
|
|
38
38
|
metadataJson: unknown;
|
|
39
39
|
revokedAt: Date | null;
|
|
40
40
|
lastRefreshedAt: Date | null;
|
|
@@ -48,7 +48,6 @@ declare class ConnectService extends BaseService<{
|
|
|
48
48
|
accessToken: string;
|
|
49
49
|
refreshToken: string | null;
|
|
50
50
|
scope: string | null;
|
|
51
|
-
parentId: string | null;
|
|
52
51
|
provider: string;
|
|
53
52
|
accountType: string;
|
|
54
53
|
providerAccountId: string;
|
|
@@ -56,6 +55,7 @@ declare class ConnectService extends BaseService<{
|
|
|
56
55
|
displayName: string | null;
|
|
57
56
|
avatarUrl: string | null;
|
|
58
57
|
tokenType: string | null;
|
|
58
|
+
parentId: string | null;
|
|
59
59
|
metadataJson: unknown;
|
|
60
60
|
revokedAt: Date | null;
|
|
61
61
|
lastRefreshedAt: Date | null;
|
|
@@ -27,11 +27,11 @@ declare function createConnectTRPC({
|
|
|
27
27
|
updatedAt?: Date | null | undefined;
|
|
28
28
|
expiresAt?: Date | null | undefined;
|
|
29
29
|
scope?: string | null | undefined;
|
|
30
|
-
parentId?: string | null | undefined;
|
|
31
30
|
handle?: string | null | undefined;
|
|
32
31
|
displayName?: string | null | undefined;
|
|
33
32
|
avatarUrl?: string | null | undefined;
|
|
34
33
|
tokenType?: string | null | undefined;
|
|
34
|
+
parentId?: string | null | undefined;
|
|
35
35
|
metadataJson?: unknown;
|
|
36
36
|
revokedAt?: Date | null | undefined;
|
|
37
37
|
lastRefreshedAt?: Date | null | undefined;
|
|
@@ -27,11 +27,11 @@ declare function createConnectTRPC({
|
|
|
27
27
|
updatedAt?: Date | null | undefined;
|
|
28
28
|
expiresAt?: Date | null | undefined;
|
|
29
29
|
scope?: string | null | undefined;
|
|
30
|
-
parentId?: string | null | undefined;
|
|
31
30
|
handle?: string | null | undefined;
|
|
32
31
|
displayName?: string | null | undefined;
|
|
33
32
|
avatarUrl?: string | null | undefined;
|
|
34
33
|
tokenType?: string | null | undefined;
|
|
34
|
+
parentId?: string | null | undefined;
|
|
35
35
|
metadataJson?: unknown;
|
|
36
36
|
revokedAt?: Date | null | undefined;
|
|
37
37
|
lastRefreshedAt?: Date | null | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runtime = require("../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_src_modules_base_base_service = require("../base/base.service.cjs");
|
|
4
|
+
let mammoth = require("mammoth");
|
|
5
|
+
mammoth = require_runtime.__toESM(mammoth);
|
|
6
|
+
let turndown = require("turndown");
|
|
7
|
+
turndown = require_runtime.__toESM(turndown);
|
|
8
|
+
//#region src/modules/docx/docx.service.ts
|
|
9
|
+
var DocxService = class extends require_src_modules_base_base_service.BaseService {
|
|
10
|
+
async convertToMarkdown(buffer) {
|
|
11
|
+
return this.throwableAsync(async () => {
|
|
12
|
+
const turndown$1 = new turndown.default();
|
|
13
|
+
const { value: html } = await mammoth.default.convertToHtml({ buffer });
|
|
14
|
+
return turndown$1.turndown(html);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.DocxService = DocxService;
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=docx.service.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docx.service.cjs","names":["BaseService","turndown","TurndownService"],"sources":["../../../../src/modules/docx/docx.service.ts"],"sourcesContent":["import mammoth from \"mammoth\";\r\nimport TurndownService from \"turndown\";\r\nimport type { ServerResultAsync } from \"../base/base.dto\";\r\nimport { BaseService } from \"../base/base.service\";\r\n\r\nexport class DocxService extends BaseService<never, never> {\r\n async convertToMarkdown(buffer: Buffer): ServerResultAsync<string> {\r\n return this.throwableAsync(async () => {\r\n const turndown = new TurndownService();\r\n const { value: html } = await mammoth.convertToHtml({ buffer });\r\n const markdown = turndown.turndown(html);\r\n return markdown;\r\n });\r\n }\r\n}\r\n"],"mappings":";;;;;;;;AAKA,IAAa,cAAb,cAAiCA,sCAAAA,YAA0B;CACzD,MAAM,kBAAkB,QAA2C;AACjE,SAAO,KAAK,eAAe,YAAY;GACrC,MAAMC,aAAW,IAAIC,SAAAA,SAAiB;GACtC,MAAM,EAAE,OAAO,SAAS,MAAM,QAAA,QAAQ,cAAc,EAAE,QAAQ,CAAC;AAE/D,UADiBD,WAAS,SAAS,KAAK;IAExC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ServerResultAsync } from "../base/base.dto.cjs";
|
|
2
|
+
import { BaseService } from "../base/base.service.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/modules/docx/docx.service.d.ts
|
|
5
|
+
declare class DocxService extends BaseService<never, never> {
|
|
6
|
+
convertToMarkdown(buffer: Buffer): ServerResultAsync<string>;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { DocxService };
|
|
10
|
+
//# sourceMappingURL=docx.service.d.cts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ServerResultAsync } from "../base/base.dto.mjs";
|
|
2
|
+
import { BaseService } from "../base/base.service.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/modules/docx/docx.service.d.ts
|
|
5
|
+
declare class DocxService extends BaseService<never, never> {
|
|
6
|
+
convertToMarkdown(buffer: Buffer): ServerResultAsync<string>;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { DocxService };
|
|
10
|
+
//# sourceMappingURL=docx.service.d.mts.map
|