arkos 1.4.9-beta → 1.4.10-beta
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/cjs/app.js +14 -14
- package/dist/cjs/components/arkos-policy/index.js +38 -0
- package/dist/cjs/components/arkos-policy/index.js.map +1 -0
- package/dist/cjs/{types/arkos-prisma-input.bak.js → components/arkos-policy/types.js} +1 -1
- package/dist/cjs/components/arkos-policy/types.js.map +1 -0
- package/dist/cjs/exports/auth/index.js +1 -1
- package/dist/cjs/exports/config.js +6 -0
- package/dist/cjs/exports/config.js.map +1 -0
- package/dist/cjs/exports/controllers/index.js +2 -2
- package/dist/cjs/exports/error-handler/index.js +2 -2
- package/dist/cjs/exports/index.js +4 -4
- package/dist/cjs/exports/middlewares/index.js +1 -1
- package/dist/cjs/exports/prisma/index.js +1 -1
- package/dist/cjs/exports/services/index.js +5 -5
- package/dist/cjs/exports/utils/index.js +2 -2
- package/dist/cjs/exports/validation/index.js +2 -2
- package/dist/cjs/modules/auth/auth.controller.js +7 -7
- package/dist/cjs/modules/auth/auth.router.js +10 -10
- package/dist/cjs/modules/auth/auth.service.js +12 -12
- package/dist/cjs/modules/auth/utils/auth-error-objects.js +1 -1
- package/dist/cjs/modules/auth/utils/helpers/auth.controller.helpers.js +2 -2
- package/dist/cjs/modules/auth/utils/services/auth-action.service.js +3 -3
- package/dist/cjs/modules/base/base.controller.js +9 -9
- package/dist/cjs/modules/base/base.middlewares.js +9 -9
- package/dist/cjs/modules/base/base.router.js +4 -4
- package/dist/cjs/modules/base/base.service.js +8 -8
- package/dist/cjs/modules/base/utils/error-prettifier.js +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.controller.helpers.js +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.middlewares.helpers.js +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.router.helpers.js +9 -9
- package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js +2 -2
- package/dist/cjs/modules/debugger/debugger.service.js +4 -4
- package/dist/cjs/modules/debugger/utils/loaded-components-logger.js +2 -2
- package/dist/cjs/modules/email/email.service.js +2 -2
- package/dist/cjs/modules/error-handler/error-handler.controller.js +2 -2
- package/dist/cjs/modules/error-handler/utils/error-handler.helpers.js +1 -1
- package/dist/cjs/modules/file-upload/file-upload.controller.js +9 -9
- package/dist/cjs/modules/file-upload/file-upload.controller.js.map +1 -1
- package/dist/cjs/modules/file-upload/file-upload.router.js +22 -22
- package/dist/cjs/modules/file-upload/file-upload.router.js.map +1 -1
- package/dist/cjs/modules/file-upload/file-upload.service.js +6 -6
- package/dist/cjs/modules/file-upload/utils/helpers/file-upload.helpers.js +3 -3
- package/dist/cjs/modules/swagger/swagger.router.js +8 -8
- package/dist/cjs/modules/swagger/utils/get-open-api-login-html.js +276 -0
- package/dist/cjs/modules/swagger/utils/get-open-api-login-html.js.map +1 -0
- package/dist/cjs/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js +3 -3
- package/dist/cjs/modules/swagger/utils/helpers/get-file-upload-json-schema-paths.js +4 -4
- package/dist/cjs/modules/swagger/utils/helpers/get-swagger-default-configs.js +1 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-class-validator-json-schemas.js +4 -4
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-prisma-json-schemas.js +2 -2
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-zod-json-schemas.js +3 -3
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js +5 -5
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-parent-routes-paths.js +3 -3
- package/dist/cjs/modules/swagger/utils/helpers/missing-json-schemas-generator.js +2 -2
- package/dist/cjs/modules/swagger/utils/helpers/openapi-schema-converter.js +3 -3
- package/dist/cjs/modules/swagger/utils/helpers/swagger.router.helpers.js +12 -12
- package/dist/cjs/server.js +5 -5
- package/dist/cjs/types/arkos-config/utils.js +3 -0
- package/dist/cjs/types/arkos-config/utils.js.map +1 -0
- package/dist/cjs/types/arkos.js +3 -0
- package/dist/cjs/types/arkos.js.map +1 -0
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/utils/arkos-router/arkos-router-openapi-manager.js +1 -1
- package/dist/cjs/utils/arkos-router/index.js +9 -9
- package/dist/cjs/utils/arkos-router/index.js.map +1 -1
- package/dist/cjs/utils/arkos-router/route-config-validator.js +2 -2
- package/dist/cjs/utils/arkos-router/types/index.js.map +1 -1
- package/dist/cjs/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +152 -0
- package/dist/cjs/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -0
- package/dist/cjs/utils/arkos-router/utils/helpers/index.js +6 -6
- package/dist/cjs/utils/arkos-router/utils/helpers/upload-manager.js +8 -8
- package/dist/cjs/utils/bundler.js +163 -0
- package/dist/cjs/utils/bundler.js.map +1 -0
- package/dist/cjs/utils/cli/build.js +21 -33
- package/dist/cjs/utils/cli/build.js.map +1 -1
- package/dist/cjs/utils/cli/dev.js +6 -5
- package/dist/cjs/utils/cli/dev.js.map +1 -1
- package/dist/cjs/utils/cli/export-auth-action.js +4 -3
- package/dist/cjs/utils/cli/export-auth-action.js.map +1 -1
- package/dist/cjs/utils/cli/generate.js +8 -8
- package/dist/cjs/utils/cli/index.js +7 -7
- package/dist/cjs/utils/cli/prisma-generate.js +3 -3
- package/dist/cjs/utils/cli/remove-dir-cli.js +1 -1
- package/dist/cjs/utils/cli/start.js +5 -5
- package/dist/cjs/utils/cli/start.js.map +1 -1
- package/dist/cjs/utils/cli/utils/cli.helpers.js +3 -3
- package/dist/cjs/utils/cli/utils/runtime-cli-commander.js +5 -5
- package/dist/cjs/utils/cli/utils/template-generator/templates/auth-configs-template.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator/create-dto-template.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator/update-dto-template.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator-dto-generator.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-multiple-components.js +3 -3
- package/dist/cjs/utils/cli/utils/template-generator/templates/hooks-template.js +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/policy-template.js +53 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/policy-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/query-options-template.js +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/service-template.js +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/zod/create-schema-template.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/zod/update-schema-template.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/zod-schema-generator.js +2 -2
- package/dist/cjs/utils/cli/utils/template-generators.js +11 -11
- package/dist/cjs/utils/cli/utils/watermark-stamper.js +3 -3
- package/dist/cjs/utils/dotenv.helpers.js +2 -2
- package/dist/cjs/utils/dynamic-loader.js +8 -8
- package/dist/cjs/utils/features/api.features.js +5 -5
- package/dist/cjs/utils/features/change-case.features.js +1 -1
- package/dist/cjs/utils/features/port-and-host-allocator.js +1 -1
- package/dist/cjs/utils/helpers/api.features.helpers.js +2 -2
- package/dist/cjs/utils/helpers/arkos-config.helpers.js +3 -3
- package/dist/cjs/utils/helpers/exit-error.js +12 -0
- package/dist/cjs/utils/helpers/exit-error.js.map +1 -0
- package/dist/cjs/utils/helpers/fs.helpers.js +1 -1
- package/dist/cjs/utils/helpers/fs.helpers.js.map +1 -1
- package/dist/cjs/utils/helpers/prisma.helpers.js +6 -6
- package/dist/cjs/utils/helpers/query-parser.helpers.js +1 -1
- package/dist/cjs/utils/helpers/routers.helpers.js +4 -4
- package/dist/cjs/utils/helpers/routers.helpers.js.map +1 -1
- package/dist/cjs/utils/initialize-app.js +56 -0
- package/dist/cjs/utils/initialize-app.js.map +1 -0
- package/dist/cjs/utils/prisma/prisma-json-schema-generator.js +4 -4
- package/dist/cjs/utils/prisma/prisma-schema-parser.js +2 -2
- package/dist/cjs/utils/setup-app.js +119 -0
- package/dist/cjs/utils/setup-app.js.map +1 -0
- package/dist/esm/components/arkos-policy/index.js +32 -0
- package/dist/esm/components/arkos-policy/index.js.map +1 -0
- package/dist/esm/components/arkos-policy/types.js +2 -0
- package/dist/esm/components/arkos-policy/types.js.map +1 -0
- package/dist/esm/exports/config.js +3 -0
- package/dist/esm/exports/config.js.map +1 -0
- package/dist/esm/modules/file-upload/file-upload.controller.js +2 -2
- package/dist/esm/modules/file-upload/file-upload.controller.js.map +1 -1
- package/dist/esm/modules/file-upload/file-upload.router.js +12 -12
- package/dist/esm/modules/file-upload/file-upload.router.js.map +1 -1
- package/dist/esm/modules/swagger/utils/get-open-api-login-html.js +273 -0
- package/dist/esm/modules/swagger/utils/get-open-api-login-html.js.map +1 -0
- package/dist/esm/types/arkos-config/utils.js +2 -0
- package/dist/esm/types/arkos-config/utils.js.map +1 -0
- package/dist/esm/types/arkos.js +2 -0
- package/dist/esm/types/arkos.js.map +1 -0
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/utils/arkos-router/index.js.map +1 -1
- package/dist/esm/utils/arkos-router/types/index.js.map +1 -1
- package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +146 -0
- package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -0
- package/dist/esm/utils/bundler.js +156 -0
- package/dist/esm/utils/bundler.js.map +1 -0
- package/dist/esm/utils/cli/build.js +15 -27
- package/dist/esm/utils/cli/build.js.map +1 -1
- package/dist/esm/utils/cli/dev.js +1 -0
- package/dist/esm/utils/cli/dev.js.map +1 -1
- package/dist/esm/utils/cli/export-auth-action.js +1 -0
- package/dist/esm/utils/cli/export-auth-action.js.map +1 -1
- package/dist/esm/utils/cli/start.js +1 -1
- package/dist/esm/utils/cli/start.js.map +1 -1
- package/dist/esm/utils/cli/utils/cli.helpers.js +1 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/policy-template.js +47 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/policy-template.js.map +1 -0
- package/dist/esm/utils/helpers/exit-error.js +6 -0
- package/dist/esm/utils/helpers/exit-error.js.map +1 -0
- package/dist/esm/utils/helpers/fs.helpers.js +1 -1
- package/dist/esm/utils/helpers/fs.helpers.js.map +1 -1
- package/dist/esm/utils/helpers/routers.helpers.js.map +1 -1
- package/dist/esm/utils/initialize-app.js +50 -0
- package/dist/esm/utils/initialize-app.js.map +1 -0
- package/dist/esm/utils/setup-app.js +113 -0
- package/dist/esm/utils/setup-app.js.map +1 -0
- package/dist/types/components/arkos-policy/index.d.ts +31 -0
- package/dist/types/components/arkos-policy/types.d.ts +21 -0
- package/dist/types/exports/config.d.ts +2 -0
- package/dist/types/modules/file-upload/file-upload.router.d.ts +1 -2
- package/dist/types/modules/swagger/utils/get-open-api-login-html.d.ts +1 -0
- package/dist/types/types/arkos-config/utils.d.ts +35 -0
- package/dist/types/types/arkos.d.ts +31 -0
- package/dist/types/types/index.d.ts +3 -5
- package/dist/types/utils/arkos-router/types/index.d.ts +20 -11
- package/dist/types/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.d.ts +7 -0
- package/dist/types/utils/bundler.d.ts +152 -0
- package/dist/types/utils/cli/utils/template-generator/templates/policy-template.d.ts +2 -0
- package/dist/types/utils/helpers/exit-error.d.ts +1 -0
- package/dist/types/utils/helpers/routers.helpers.d.ts +3 -3
- package/dist/types/utils/initialize-app.d.ts +2 -0
- package/dist/types/utils/setup-app.d.ts +2 -0
- package/package.json +1 -1
- package/dist/cjs/types/arkos-prisma-input.bak.js.map +0 -1
- package/dist/cjs/utils/cli/utils/static-types-generator.js +0 -558
- package/dist/cjs/utils/cli/utils/static-types-generator.js.map +0 -1
- package/dist/esm/types/arkos-prisma-input.bak.js +0 -2
- package/dist/esm/types/arkos-prisma-input.bak.js.map +0 -1
- package/dist/esm/utils/cli/utils/static-types-generator.js +0 -553
- package/dist/esm/utils/cli/utils/static-types-generator.js.map +0 -1
- package/dist/types/types/arkos-prisma-input.bak.d.ts +0 -237
- package/dist/types/utils/cli/utils/static-types-generator.d.ts +0 -36
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AA6LA,MAAM,CAAN,IAAY,oBAKX;AALD,WAAY,oBAAoB;IAC9B,yCAAiB,CAAA;IACjB,qCAAa,CAAA;IACb,yCAAiB,CAAA;IACjB,yCAAiB,CAAA;AACnB,CAAC,EALW,oBAAoB,KAApB,oBAAoB,QAK/B","sourcesContent":["import {\n ErrorRequestHandler,\n NextFunction,\n Request,\n RequestHandler,\n Response,\n} from \"express\";\n\nexport type PrismaOperations = \"findMany\";\n\n/**\n * Type definition for authentication-related Prisma query operations\n * @template T - The Prisma model delegate type\n */\nexport type AuthPrismaQueryOptions<T extends Record<string, any>> = {\n // User profile endpoints\n /**\n * Options for retrieving the current authenticated user's profile\n */\n getMe?: Partial<Parameters<T[\"findUnique\"]>[0]>;\n /**\n * Options for updating the current authenticated user's profile\n */\n updateMe?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for soft deleting or deactivating the current authenticated user's account\n */\n deleteMe?: Partial<Parameters<T[\"update\"]>[0]>;\n // Authentication endpoints\n /**\n * Options for user login authentication queries\n */\n login?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for user registration and account creation\n */\n signup?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for updating the current authenticated user's password\n */\n updatePassword?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for finding multiple auth actions\n */\n findManyAuthAction?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for finding a single auth action\n */\n findOneAuthAction?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n};\n\n/**\n * Base Prisma query options for standard CRUD operations\n * @template T - The Prisma model delegate type\n */\ntype BasePrismaQueryOptions<T extends Record<string, any>> = {\n /**\n * @deprecated Use `global` instead for general query options\n */\n queryOptions?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Global query options that can be used for all operations\n * Replaces the deprecated queryOptions\n */\n global?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General find options for findMany and findOne operations\n */\n find?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General create options for createOne and createMany operations\n */\n create?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * General update options for updateOne and updateMany operations\n */\n update?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * General delete options for deleteOne and deleteMany operations\n */\n delete?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * General save options for createOne, createMany, updateOne, updateMany operations\n */\n save?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for single record operations (createOne, updateOne)\n */\n saveOne?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for multiple record operations (createMany, updateMany)\n */\n saveMany?:\n | Partial<Parameters<T[\"createMany\"]>[0]>\n | Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for finding a single record (first match)\n */\n findOne?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for finding multiple records\n */\n findMany?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for creating a single record\n */\n createOne?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for creating multiple records\n */\n createMany?: Partial<Parameters<T[\"createMany\"]>[0]>;\n /**\n * Options for updating a single record\n */\n updateOne?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for updating multiple records\n */\n updateMany?: Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for deleting a single record\n */\n deleteOne?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * Options for deleting multiple records\n */\n deleteMany?: Partial<Parameters<T[\"deleteMany\"]>[0]>;\n};\n\n/**\n * Type definition for Prisma query operations with flexible options\n * Conditionally provides auth-specific options when ModelName is \"auth\"\n * @template T - The Prisma model delegate type\n * @template ModelName - The model name (defaults to string for standard models)\n */\nexport type PrismaQueryOptions<\n T extends Record<string, any>,\n ModelName extends string = string,\n> = ModelName extends \"auth\"\n ? AuthPrismaQueryOptions<T>\n : BasePrismaQueryOptions<T>;\n/**\n * Interface defining the minimum structure required for Prisma model delegates\n * This allows us to constraint TModel without requiring Prisma imports\n */\nexport type PrismaModelDelegate = {\n create: (args: { data: never; [key: string]: never }) => Promise<any>;\n createMany: (args: { data: never; [key: string]: never }) => Promise<any>;\n findMany: (args: { [key: string]: never }) => Promise<any[]>;\n findFirst: (args: { where: never; [key: string]: never }) => Promise<any>;\n findUnique: (args: { where: never; [key: string]: never }) => Promise<any>;\n update: (args: {\n where: never;\n data: never;\n [key: string]: never;\n }) => Promise<any>;\n updateMany: (args: {\n where: never;\n data: never;\n [key: string]: never;\n }) => Promise<any>;\n delete: (args: { where: never; [key: string]: never }) => Promise<any>;\n deleteMany: (args: { where: never; [key: string]: never }) => Promise<any>;\n count: (args: { where: never; [key: string]: never }) => Promise<number>;\n};\n\nexport interface UserRole {\n id: string;\n createdAt: Date;\n deletedAt?: Date;\n roleId: string;\n role: AuthRole;\n user: User;\n userId: string;\n}\n\nexport interface AuthRole {\n id: string;\n createdAt: Date;\n deletedAt?: Date;\n name: string;\n permissions: AuthPermission[];\n userRoles: UserRole[];\n}\n\nexport enum AuthPermissionAction {\n Create = \"Create\",\n View = \"View\",\n Update = \"Update\",\n Delete = \"Delete\",\n}\n\nexport interface AuthPermission {\n id: string;\n createdAt: Date;\n deletedAt?: Date;\n resource: string;\n action: AuthPermissionAction;\n roleId: string;\n role: AuthRole;\n}\n\nexport interface User extends Record<string, any> {\n id: string;\n isSuperUser: boolean;\n password: string;\n passwordChangedAt?: Date;\n deletedSelfAccountAt: Date;\n isActive: boolean;\n}\n\nexport interface ArkosRequest<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n Query extends Record<string, any> = any,\n> extends Request<P, ResBody, ReqBody, Query> {\n /**\n * Authenticated user with additional fields\n */\n user?: User & Record<string, any>;\n /**\n * Single uploaded file, populated when using `multer.single()`\n */\n file?: Express.Multer.File;\n /**\n * Uploaded files, populated when using `multer.array()` or `multer.fields()`.\n */\n files?: Express.Multer.File[] | Record<string, Express.Multer.File[]>;\n\n /**\n * Fields to include in relational queries\n */\n relationFields?: Record<string, boolean>;\n\n /**\n * Prisma include options for related data\n */\n include?: Record<string, any>;\n\n /**\n * Data to be sent in the response\n */\n responseData?: Record<string, any> | null;\n\n /**\n * Additional context data\n */\n additionalData?: Record<string, any> | null;\n\n /**\n * HTTP status code for the response\n */\n responseStatus?: number;\n\n /**\n * Typed request body\n */\n body: ReqBody;\n\n /**\n * Prisma query options (where, orderBy, select, etc.)\n */\n prismaQueryOptions?: Record<string, any>;\n\n /**\n * Typed query parameters\n */\n query: Query;\n\n /**\n * JWT token used in authentication process\n */\n accessToken?: string;\n\n /**\n * Query parameters after being handled and transformed by middleware\n */\n transformedQuery?: Record<string, any>;\n\n /**\n * Processed filters from APIFeatures.filters\n */\n filters?: Record<string, any>;\n\n /**\n * Name of the Prisma model being queried\n */\n modelName?: string;\n}\n\nexport interface ArkosResponse<\n ResBody = any,\n Locals extends Record<string, any> = Record<string, any>,\n> extends Response<ResBody, Locals> {}\n\nexport interface ArkosNextFunction extends NextFunction {}\n\nexport
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AA6LA,MAAM,CAAN,IAAY,oBAKX;AALD,WAAY,oBAAoB;IAC9B,yCAAiB,CAAA;IACjB,qCAAa,CAAA;IACb,yCAAiB,CAAA;IACjB,yCAAiB,CAAA;AACnB,CAAC,EALW,oBAAoB,KAApB,oBAAoB,QAK/B","sourcesContent":["import {\n ErrorRequestHandler,\n NextFunction,\n Request,\n RequestHandler,\n Response,\n} from \"express\";\n\nexport type PrismaOperations = \"findMany\";\n\n/**\n * Type definition for authentication-related Prisma query operations\n * @template T - The Prisma model delegate type\n */\nexport type AuthPrismaQueryOptions<T extends Record<string, any>> = {\n // User profile endpoints\n /**\n * Options for retrieving the current authenticated user's profile\n */\n getMe?: Partial<Parameters<T[\"findUnique\"]>[0]>;\n /**\n * Options for updating the current authenticated user's profile\n */\n updateMe?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for soft deleting or deactivating the current authenticated user's account\n */\n deleteMe?: Partial<Parameters<T[\"update\"]>[0]>;\n // Authentication endpoints\n /**\n * Options for user login authentication queries\n */\n login?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for user registration and account creation\n */\n signup?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for updating the current authenticated user's password\n */\n updatePassword?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for finding multiple auth actions\n */\n findManyAuthAction?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for finding a single auth action\n */\n findOneAuthAction?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n};\n\n/**\n * Base Prisma query options for standard CRUD operations\n * @template T - The Prisma model delegate type\n */\ntype BasePrismaQueryOptions<T extends Record<string, any>> = {\n /**\n * @deprecated Use `global` instead for general query options\n */\n queryOptions?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Global query options that can be used for all operations\n * Replaces the deprecated queryOptions\n */\n global?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General find options for findMany and findOne operations\n */\n find?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General create options for createOne and createMany operations\n */\n create?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * General update options for updateOne and updateMany operations\n */\n update?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * General delete options for deleteOne and deleteMany operations\n */\n delete?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * General save options for createOne, createMany, updateOne, updateMany operations\n */\n save?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for single record operations (createOne, updateOne)\n */\n saveOne?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for multiple record operations (createMany, updateMany)\n */\n saveMany?:\n | Partial<Parameters<T[\"createMany\"]>[0]>\n | Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for finding a single record (first match)\n */\n findOne?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for finding multiple records\n */\n findMany?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for creating a single record\n */\n createOne?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for creating multiple records\n */\n createMany?: Partial<Parameters<T[\"createMany\"]>[0]>;\n /**\n * Options for updating a single record\n */\n updateOne?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for updating multiple records\n */\n updateMany?: Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for deleting a single record\n */\n deleteOne?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * Options for deleting multiple records\n */\n deleteMany?: Partial<Parameters<T[\"deleteMany\"]>[0]>;\n};\n\n/**\n * Type definition for Prisma query operations with flexible options\n * Conditionally provides auth-specific options when ModelName is \"auth\"\n * @template T - The Prisma model delegate type\n * @template ModelName - The model name (defaults to string for standard models)\n */\nexport type PrismaQueryOptions<\n T extends Record<string, any>,\n ModelName extends string = string,\n> = ModelName extends \"auth\"\n ? AuthPrismaQueryOptions<T>\n : BasePrismaQueryOptions<T>;\n/**\n * Interface defining the minimum structure required for Prisma model delegates\n * This allows us to constraint TModel without requiring Prisma imports\n */\nexport type PrismaModelDelegate = {\n create: (args: { data: never; [key: string]: never }) => Promise<any>;\n createMany: (args: { data: never; [key: string]: never }) => Promise<any>;\n findMany: (args: { [key: string]: never }) => Promise<any[]>;\n findFirst: (args: { where: never; [key: string]: never }) => Promise<any>;\n findUnique: (args: { where: never; [key: string]: never }) => Promise<any>;\n update: (args: {\n where: never;\n data: never;\n [key: string]: never;\n }) => Promise<any>;\n updateMany: (args: {\n where: never;\n data: never;\n [key: string]: never;\n }) => Promise<any>;\n delete: (args: { where: never; [key: string]: never }) => Promise<any>;\n deleteMany: (args: { where: never; [key: string]: never }) => Promise<any>;\n count: (args: { where: never; [key: string]: never }) => Promise<number>;\n};\n\nexport interface UserRole {\n id: string;\n createdAt: Date;\n deletedAt?: Date;\n roleId: string;\n role: AuthRole;\n user: User;\n userId: string;\n}\n\nexport interface AuthRole {\n id: string;\n createdAt: Date;\n deletedAt?: Date;\n name: string;\n permissions: AuthPermission[];\n userRoles: UserRole[];\n}\n\nexport enum AuthPermissionAction {\n Create = \"Create\",\n View = \"View\",\n Update = \"Update\",\n Delete = \"Delete\",\n}\n\nexport interface AuthPermission {\n id: string;\n createdAt: Date;\n deletedAt?: Date;\n resource: string;\n action: AuthPermissionAction;\n roleId: string;\n role: AuthRole;\n}\n\nexport interface User extends Record<string, any> {\n id: string;\n isSuperUser: boolean;\n password: string;\n passwordChangedAt?: Date;\n deletedSelfAccountAt: Date;\n isActive: boolean;\n}\n\nexport interface ArkosRequest<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n Query extends Record<string, any> = any,\n> extends Request<P, ResBody, ReqBody, Query> {\n /**\n * Authenticated user with additional fields\n */\n user?: User & Record<string, any>;\n /**\n * Single uploaded file, populated when using `multer.single()`\n */\n file?: Express.Multer.File;\n /**\n * Uploaded files, populated when using `multer.array()` or `multer.fields()`.\n */\n files?: Express.Multer.File[] | Record<string, Express.Multer.File[]>;\n\n /**\n * Fields to include in relational queries\n */\n relationFields?: Record<string, boolean>;\n\n /**\n * Prisma include options for related data\n */\n include?: Record<string, any>;\n\n /**\n * Data to be sent in the response\n */\n responseData?: Record<string, any> | null;\n\n /**\n * Additional context data\n */\n additionalData?: Record<string, any> | null;\n\n /**\n * HTTP status code for the response\n */\n responseStatus?: number;\n\n /**\n * Typed request body\n */\n body: ReqBody;\n\n /**\n * Prisma query options (where, orderBy, select, etc.)\n */\n prismaQueryOptions?: Record<string, any>;\n\n /**\n * Typed query parameters\n */\n query: Query;\n\n /**\n * JWT token used in authentication process\n */\n accessToken?: string;\n\n /**\n * Query parameters after being handled and transformed by middleware\n */\n transformedQuery?: Record<string, any>;\n\n /**\n * Processed filters from APIFeatures.filters\n */\n filters?: Record<string, any>;\n\n /**\n * Name of the Prisma model being queried\n */\n modelName?: string;\n}\n\nexport interface ArkosResponse<\n ResBody = any,\n Locals extends Record<string, any> = Record<string, any>,\n> extends Response<ResBody, Locals> {}\n\nexport interface ArkosNextFunction extends NextFunction {}\n\nexport type ArkosRequestHandler<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n ReqQuery extends Record<string, any> = any,\n Locals extends Record<string, any> = Record<string, any>,\n> = (\n req: ArkosRequest<P, ResBody, ReqBody, ReqQuery>,\n res: ArkosResponse<ResBody, Locals>,\n next: ArkosNextFunction\n) => void | Promise<void>;\n\nexport type ArkosErrorRequestHandler<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n ReqQuery extends Record<string, any> = any,\n Locals extends Record<string, any> = Record<string, any>,\n> = (\n err: any,\n req: ArkosRequest<P, ResBody, ReqBody, ReqQuery>,\n res: ArkosResponse<ResBody, Locals>,\n next: ArkosNextFunction\n) => void | Promise<void>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/arkos-router/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Router, RouterOptions } from \"express\";\nimport {\n IArkosRouter,\n ArkosRouteConfig,\n ArkosAnyRequestHandler,\n PathParams,\n ArkosIRoute,\n} from \"./types\";\nimport { OpenAPIV3 } from \"openapi-types\";\nimport RouteConfigValidator from \"./route-config-validator\";\nimport RouteConfigRegistry from \"./route-config-registry\";\nimport {\n extractArkosRoutes,\n extractPathParams,\n getMiddlewareStack,\n} from \"./utils/helpers\";\nimport { getArkosConfig } from \"../../exports\";\nimport { catchAsync } from \"../../exports/error-handler\";\nimport zodToJsonSchema from \"zod-to-json-schema\";\nimport classValidatorToJsonSchema from \"../../modules/swagger/utils/helpers/class-validator-to-json-schema\";\nimport openApiSchemaConverter from \"../../modules/swagger/utils/helpers/openapi-schema-converter\";\nimport uploadManager from \"./utils/helpers/upload-manager\";\nimport { getUserFileExtension } from \"../helpers/fs.helpers\";\n\n/**\n * Creates an enhanced Express Router with features like OpenAPI documentation capabilities and smart data validation.\n *\n * The ArkosRouter extends the standard Express Router with the ability to\n * automatically capture OpenAPI metadata from route configurations.\n *\n * @example\n * const router = ArkosRouter();\n *\n * router.get(\n * {\n * path: \"/users/:id\",\n * openapi: {\n * summary: \"Get user by ID\",\n * tags: [\"Users\"]\n * }\n * },\n * (req, res) => { ... }\n * );\n *\n * @returns {IArkosRouter} A proxied Express Router instance with enhanced OpenAPI capabilities\n *\n * @see {@link ArkosRouteConfig} for configuration options\n */\nexport default function ArkosRouter(options?: RouterOptions): IArkosRouter {\n const router = Router(options);\n\n return new Proxy(router, {\n get(target, prop, receiver) {\n const originalMethod = Reflect.get(target, prop, receiver);\n\n const httpMethods = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"all\",\n \"head\",\n \"trace\",\n \"options\",\n ] as const;\n\n if (prop === \"route\") {\n return function (path: PathParams) {\n const routeChain: any = {};\n\n httpMethods.forEach((method) => {\n routeChain[method] = function (\n config: ArkosAnyRequestHandler | Omit<ArkosRouteConfig, \"path\">,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n const fullConfig: ArkosRouteConfig = {\n ...config,\n path,\n };\n\n receiver[method](fullConfig, ...handlers);\n\n return routeChain as ArkosIRoute;\n };\n });\n\n return routeChain;\n };\n }\n\n if (httpMethods.includes(prop as any)) {\n return function (\n config: ArkosRouteConfig,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n if (config.disabled) return;\n\n const path = config.path;\n\n if (!RouteConfigValidator.isArkosRouteConfig(config))\n throw Error(\n `First argument of ArkosRouter().${prop as string}() must be a valid ArkosRouteConfig object with path field, but recevied ${typeof config === \"object\" ? JSON.stringify(config, null, 2) : config}`\n );\n\n if ([null, undefined].includes(path as any))\n throw Error(\n \"Please pass valid value for path field to use in your route\"\n );\n\n const method = prop as string;\n const UndefinedHandlerError = (handler: any) =>\n Error(\n `Wrong value for handler in route ${method.toUpperCase()} ${path}, recevied ${handler}.`\n );\n\n if (handlers.length > 0) {\n const flattenHandlers = (arr: any[]): ArkosAnyRequestHandler[] => {\n return arr.reduce((flat, item) => {\n return flat.concat(\n Array.isArray(item) ? flattenHandlers(item) : item\n );\n }, []);\n };\n\n const flatHandlers = flattenHandlers(handlers);\n\n handlers = flatHandlers.map((handler: ArkosAnyRequestHandler) => {\n if (!handler) throw UndefinedHandlerError(handler);\n\n if (typeof handler !== \"function\") {\n throw UndefinedHandlerError(handler);\n }\n\n return catchAsync(handler, {\n type: handler.length > 3 ? \"error\" : \"normal\",\n });\n });\n\n const finalHandler = handlers[handlers.length - 1];\n RouteConfigRegistry.register(finalHandler, config, method);\n }\n\n const arkosConfig = getArkosConfig();\n const validationConfig = arkosConfig.validation;\n const authenticationConfig = arkosConfig.authentication;\n const strictValidation = validationConfig?.strict;\n const route = `${method.toUpperCase()} ${path}`;\n\n if (\n strictValidation &&\n (!(\"validation\" in config) ||\n (\"validation\" in config &&\n !config.validation &&\n config.validation !== undefined))\n )\n throw Error(\n \"When using strict validation you must either pass { validation: false } in order to explicitly tell that no input will be received, or pass `undefined` for each input type e.g { validation: { query: undefined } } in order to deny the input of given request input.\"\n );\n\n if (\n !validationConfig?.resolver &&\n Object.keys(config.validation || {}).length > 0\n )\n throw Error(\n `Trying to pass validators into route ${route} config validation option without choosing a validation resolver under arkos.init({ validation: { resolver: '' } })`\n );\n\n if (config.authentication && !authenticationConfig?.mode)\n throw Error(\n `Trying to authenticate route ${route} without choosing an authentication mode under arkos.config.${getUserFileExtension()}\n\nFor further help see https://www.arkosjs.com/docs/core-concepts/authentication-system.`\n );\n\n handlers = [...getMiddlewareStack(config), ...handlers];\n\n if (\n config.experimental?.uploads &&\n config.experimental.uploads.deleteOnError !== false\n )\n handlers.push(\n catchAsync(\n uploadManager.handleFileCleanup(config.experimental.uploads),\n { type: \"error\" }\n )\n );\n\n return originalMethod.call(target, path, ...handlers);\n };\n }\n // }\n return originalMethod;\n },\n }) as IArkosRouter;\n}\n\nexport function generateOpenAPIFromApp(app: any) {\n const routes = extractArkosRoutes(app);\n const arkosConfig = getArkosConfig();\n\n let paths: Record<\n string,\n Record<string, Partial<OpenAPIV3.OperationObject>>\n > = {};\n\n routes.forEach(({ path, method, config }) => {\n if (config?.experimental?.openapi === false) return;\n const originalPath = path;\n\n const pathParatemersFromRoutePath = extractPathParams(path);\n for (const parameter of pathParatemersFromRoutePath) {\n path = path.replaceAll(\n `:${parameter}`,\n parameter.endsWith(\"?\") ? `{${parameter}}?` : `{${parameter}}`\n );\n }\n\n if (!paths[path]) paths[path] = {};\n\n if (typeof config?.experimental?.openapi === \"boolean\") {\n config = {\n ...config,\n experimental: {\n ...config.experimental,\n openapi: {},\n },\n };\n }\n\n const openapi =\n typeof config?.experimental?.openapi === \"object\" &&\n config.experimental.openapi !== null\n ? config.experimental.openapi\n : {};\n\n const validatorToJsonSchema =\n arkosConfig?.validation?.resolver === \"zod\"\n ? zodToJsonSchema\n : classValidatorToJsonSchema;\n\n let parameters = [];\n const validationToParameterMapping = {\n query: \"query\",\n params: \"path\",\n headers: \"header\",\n cookies: \"cookie\",\n };\n\n if (typeof config?.validation !== \"boolean\" && config?.validation) {\n for (const [key, val] of Object.entries(config?.validation)) {\n if ([\"body\"].includes(key)) continue;\n if ((config?.validation as any)[key]) {\n const jsonSchema = validatorToJsonSchema(val as any);\n const params = openApiSchemaConverter.jsonSchemaToOpenApiParameters(\n (validationToParameterMapping as any)[key],\n jsonSchema\n );\n parameters.push(...params);\n }\n }\n }\n\n const convertedOpenAPI =\n openApiSchemaConverter.convertOpenAPIConfig(openapi);\n\n const allParameters: OpenAPIV3.ParameterObject[] = [\n ...(convertedOpenAPI.parameters || []),\n ...parameters,\n ];\n\n for (const parameter of pathParatemersFromRoutePath) {\n if (\n !allParameters.find(\n ({ name, in: paramIn }) =>\n name === parameter.replace(\"?\", \"\") && paramIn === \"path\"\n )\n )\n allParameters.push({\n name: parameter,\n in: \"path\",\n required: !parameter.includes(\"?\"),\n schema: { type: \"string\" },\n });\n }\n\n for (const param of allParameters) {\n if (\n !pathParatemersFromRoutePath.includes(param.name) &&\n !pathParatemersFromRoutePath.includes(`${param.name}?`) &&\n param.in === \"path\"\n )\n throw new Error(\n `ValidationError: Trying to define path parameter '${param.name}' but it is not present in your pathname ${originalPath}`\n );\n }\n\n delete convertedOpenAPI.parameters;\n\n (paths as any)[path][method.toLowerCase()] = {\n summary: openapi?.summary || `${path}`,\n description: openapi?.description || `${method} ${path}`,\n tags: openapi?.tags || [\"Defaults\"],\n operationId: `${method.toLowerCase()}:${path}`,\n parameters: allParameters,\n ...(!convertedOpenAPI.requestBody &&\n config?.validation &&\n config?.validation?.body && {\n requestBody: {\n content: {\n \"application/json\": {\n schema: validatorToJsonSchema(config?.validation?.body as any),\n },\n },\n },\n }),\n ...convertedOpenAPI,\n };\n });\n\n return paths;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/arkos-router/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Router, RouterOptions } from \"express\";\nimport {\n IArkosRouter,\n ArkosRouteConfig,\n ArkosAnyRequestHandler,\n PathParams,\n IArkosRoute,\n} from \"./types\";\nimport { OpenAPIV3 } from \"openapi-types\";\nimport RouteConfigValidator from \"./route-config-validator\";\nimport RouteConfigRegistry from \"./route-config-registry\";\nimport {\n extractArkosRoutes,\n extractPathParams,\n getMiddlewareStack,\n} from \"./utils/helpers\";\nimport { getArkosConfig } from \"../../exports\";\nimport { catchAsync } from \"../../exports/error-handler\";\nimport zodToJsonSchema from \"zod-to-json-schema\";\nimport classValidatorToJsonSchema from \"../../modules/swagger/utils/helpers/class-validator-to-json-schema\";\nimport openApiSchemaConverter from \"../../modules/swagger/utils/helpers/openapi-schema-converter\";\nimport uploadManager from \"./utils/helpers/upload-manager\";\nimport { getUserFileExtension } from \"../helpers/fs.helpers\";\n\n/**\n * Creates an enhanced Express Router with features like OpenAPI documentation capabilities and smart data validation.\n *\n * The ArkosRouter extends the standard Express Router with the ability to\n * automatically capture OpenAPI metadata from route configurations.\n *\n * @example\n * const router = ArkosRouter();\n *\n * router.get(\n * {\n * path: \"/users/:id\",\n * openapi: {\n * summary: \"Get user by ID\",\n * tags: [\"Users\"]\n * }\n * },\n * (req, res) => { ... }\n * );\n *\n * @returns {IArkosRouter} A proxied Express Router instance with enhanced OpenAPI capabilities\n *\n * @see {@link ArkosRouteConfig} for configuration options\n */\nexport default function ArkosRouter(options?: RouterOptions): IArkosRouter {\n const router = Router(options);\n\n return new Proxy(router, {\n get(target, prop, receiver) {\n const originalMethod = Reflect.get(target, prop, receiver);\n\n const httpMethods = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"all\",\n \"head\",\n \"trace\",\n \"options\",\n ] as const;\n\n if (prop === \"route\") {\n return function (path: PathParams) {\n const routeChain: any = {};\n\n httpMethods.forEach((method) => {\n routeChain[method] = function (\n config: ArkosAnyRequestHandler | Omit<ArkosRouteConfig, \"path\">,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n const fullConfig: ArkosRouteConfig = {\n ...config,\n path,\n };\n\n receiver[method](fullConfig, ...handlers);\n\n return routeChain as IArkosRoute;\n };\n });\n\n return routeChain;\n };\n }\n\n if (httpMethods.includes(prop as any)) {\n return function (\n config: ArkosRouteConfig,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n if (config.disabled) return;\n\n const path = config.path;\n\n if (!RouteConfigValidator.isArkosRouteConfig(config))\n throw Error(\n `First argument of ArkosRouter().${prop as string}() must be a valid ArkosRouteConfig object with path field, but recevied ${typeof config === \"object\" ? JSON.stringify(config, null, 2) : config}`\n );\n\n if ([null, undefined].includes(path as any))\n throw Error(\n \"Please pass valid value for path field to use in your route\"\n );\n\n const method = prop as string;\n const UndefinedHandlerError = (handler: any) =>\n Error(\n `Wrong value for handler in route ${method.toUpperCase()} ${path}, recevied ${handler}.`\n );\n\n if (handlers.length > 0) {\n const flattenHandlers = (arr: any[]): ArkosAnyRequestHandler[] => {\n return arr.reduce((flat, item) => {\n return flat.concat(\n Array.isArray(item) ? flattenHandlers(item) : item\n );\n }, []);\n };\n\n const flatHandlers = flattenHandlers(handlers);\n\n handlers = flatHandlers.map((handler: ArkosAnyRequestHandler) => {\n if (!handler) throw UndefinedHandlerError(handler);\n\n if (typeof handler !== \"function\") {\n throw UndefinedHandlerError(handler);\n }\n\n return catchAsync(handler, {\n type: handler.length > 3 ? \"error\" : \"normal\",\n });\n });\n\n const finalHandler = handlers[handlers.length - 1];\n RouteConfigRegistry.register(finalHandler, config, method);\n }\n\n const arkosConfig = getArkosConfig();\n const validationConfig = arkosConfig.validation;\n const authenticationConfig = arkosConfig.authentication;\n const strictValidation = validationConfig?.strict;\n const route = `${method.toUpperCase()} ${path}`;\n\n if (\n strictValidation &&\n (!(\"validation\" in config) ||\n (\"validation\" in config &&\n !config.validation &&\n config.validation !== undefined))\n )\n throw Error(\n \"When using strict validation you must either pass { validation: false } in order to explicitly tell that no input will be received, or pass `undefined` for each input type e.g { validation: { query: undefined } } in order to deny the input of given request input.\"\n );\n\n if (\n !validationConfig?.resolver &&\n Object.keys(config.validation || {}).length > 0\n )\n throw Error(\n `Trying to pass validators into route ${route} config validation option without choosing a validation resolver under arkos.init({ validation: { resolver: '' } })`\n );\n\n if (config.authentication && !authenticationConfig?.mode)\n throw Error(\n `Trying to authenticate route ${route} without choosing an authentication mode under arkos.config.${getUserFileExtension()}\n\nFor further help see https://www.arkosjs.com/docs/core-concepts/authentication-system.`\n );\n\n handlers = [...getMiddlewareStack(config), ...handlers];\n\n if (\n config.experimental?.uploads &&\n config.experimental.uploads.deleteOnError !== false\n )\n handlers.push(\n catchAsync(\n uploadManager.handleFileCleanup(config.experimental.uploads),\n { type: \"error\" }\n )\n );\n\n return originalMethod.call(target, path, ...handlers);\n };\n }\n // }\n return originalMethod;\n },\n }) as IArkosRouter;\n}\n\nexport function generateOpenAPIFromApp(app: any) {\n const routes = extractArkosRoutes(app);\n const arkosConfig = getArkosConfig();\n\n let paths: Record<\n string,\n Record<string, Partial<OpenAPIV3.OperationObject>>\n > = {};\n\n routes.forEach(({ path, method, config }) => {\n if (config?.experimental?.openapi === false) return;\n const originalPath = path;\n\n const pathParatemersFromRoutePath = extractPathParams(path);\n for (const parameter of pathParatemersFromRoutePath) {\n path = path.replaceAll(\n `:${parameter}`,\n parameter.endsWith(\"?\") ? `{${parameter}}?` : `{${parameter}}`\n );\n }\n\n if (!paths[path]) paths[path] = {};\n\n if (typeof config?.experimental?.openapi === \"boolean\") {\n config = {\n ...config,\n experimental: {\n ...config.experimental,\n openapi: {},\n },\n };\n }\n\n const openapi =\n typeof config?.experimental?.openapi === \"object\" &&\n config.experimental.openapi !== null\n ? config.experimental.openapi\n : {};\n\n const validatorToJsonSchema =\n arkosConfig?.validation?.resolver === \"zod\"\n ? zodToJsonSchema\n : classValidatorToJsonSchema;\n\n let parameters = [];\n const validationToParameterMapping = {\n query: \"query\",\n params: \"path\",\n headers: \"header\",\n cookies: \"cookie\",\n };\n\n if (typeof config?.validation !== \"boolean\" && config?.validation) {\n for (const [key, val] of Object.entries(config?.validation)) {\n if ([\"body\"].includes(key)) continue;\n if ((config?.validation as any)[key]) {\n const jsonSchema = validatorToJsonSchema(val as any);\n const params = openApiSchemaConverter.jsonSchemaToOpenApiParameters(\n (validationToParameterMapping as any)[key],\n jsonSchema\n );\n parameters.push(...params);\n }\n }\n }\n\n const convertedOpenAPI =\n openApiSchemaConverter.convertOpenAPIConfig(openapi);\n\n const allParameters: OpenAPIV3.ParameterObject[] = [\n ...(convertedOpenAPI.parameters || []),\n ...parameters,\n ];\n\n for (const parameter of pathParatemersFromRoutePath) {\n if (\n !allParameters.find(\n ({ name, in: paramIn }) =>\n name === parameter.replace(\"?\", \"\") && paramIn === \"path\"\n )\n )\n allParameters.push({\n name: parameter,\n in: \"path\",\n required: !parameter.includes(\"?\"),\n schema: { type: \"string\" },\n });\n }\n\n for (const param of allParameters) {\n if (\n !pathParatemersFromRoutePath.includes(param.name) &&\n !pathParatemersFromRoutePath.includes(`${param.name}?`) &&\n param.in === \"path\"\n )\n throw new Error(\n `ValidationError: Trying to define path parameter '${param.name}' but it is not present in your pathname ${originalPath}`\n );\n }\n\n delete convertedOpenAPI.parameters;\n\n (paths as any)[path][method.toLowerCase()] = {\n summary: openapi?.summary || `${path}`,\n description: openapi?.description || `${method} ${path}`,\n tags: openapi?.tags || [\"Defaults\"],\n operationId: `${method.toLowerCase()}:${path}`,\n parameters: allParameters,\n ...(!convertedOpenAPI.requestBody &&\n config?.validation &&\n config?.validation?.body && {\n requestBody: {\n content: {\n \"application/json\": {\n schema: validatorToJsonSchema(config?.validation?.body as any),\n },\n },\n },\n }),\n ...convertedOpenAPI,\n };\n });\n\n return paths;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/utils/arkos-router/types/index.ts"],"names":[],"mappings":"","sourcesContent":["import { IRoute, IRouter } from \"express\";\nimport { ZodSchema } from \"zod\";\nimport { Options as RateLimitOptions } from \"express-rate-limit\";\nimport { Options as QueryParserOptions } from \"../../../utils/helpers/query-parser.helpers\";\nimport { DetailedAccessControlRule } from \"../../../types/auth\";\nimport { ArkosErrorRequestHandler, ArkosRequestHandler } from \"../../../types\";\nimport compression from \"compression\";\nimport { OpenApiConfig } from \"./openapi-config\";\nimport { UploadConfig } from \"./upload-config\";\nimport { BodyParserConfig } from \"./body-parser-config\";\n\nexport type PathParams = string | RegExp | Array<string | RegExp>;\n\nexport type ArkosAnyRequestHandler =\n | ArkosRequestHandler\n | ArkosErrorRequestHandler\n | Array<ArkosRequestHandler | ArkosErrorRequestHandler>;\n\n/**\n * Handler function for HTTP methods that accepts route configuration and request handlers.\n *\n * @param {ArkosRouteConfig} config - The route configuration object.\n * @param {...(ArkosRequestHandler | ArkosErrorRequestHandler)[]} handlers - Request and error handlers for the route.\n * @returns {IRouter} The Express router instance.\n */\ntype RouterMethodHandler<T> = (\n config: ArkosRouteConfig | PathParams,\n ...handlers: Array<ArkosAnyRequestHandler>\n) => T;\n\nexport type ArkosRouteMethodHandler<T> = (\n config: ArkosAnyRequestHandler | Omit<ArkosRouteConfig, \"path\">,\n ...handlers: Array<\n | ArkosRequestHandler\n | ArkosErrorRequestHandler\n | Array<ArkosRequestHandler | ArkosErrorRequestHandler>\n >\n) => T;\n\nexport interface ArkosIRoute extends IRoute {\n /** GET method handler with route configuration support */\n get: ArkosRouteMethodHandler<this>;\n /** POST method handler with route configuration support */\n post: ArkosRouteMethodHandler<this>;\n /** PUT method handler with route configuration support */\n put: ArkosRouteMethodHandler<this>;\n /** PATCH method handler with route configuration support */\n patch: ArkosRouteMethodHandler<this>;\n /** DELETE method handler with route configuration support */\n delete: ArkosRouteMethodHandler<this>;\n /** OPTIONS method handler with route configuration support */\n options: ArkosRouteMethodHandler<this>;\n /** HEAD method handler with route configuration support */\n head: ArkosRouteMethodHandler<this>;\n // /** TRACE method handler with route configuration support */\n trace: ArkosRouteMethodHandler<this>;\n /** ALL methods handler with route configuration support */\n all: ArkosRouteMethodHandler<this>;\n}\n\n/**\n * Creates an enhanced Express Router with features like OpenAPI documentation capabilities and smart data validation.\n *\n * The ArkosRouter extends the standard Express Router with the ability to\n * automatically capture OpenAPI metadata from route configurations.\n *\n * @example\n * const router = ArkosRouter();\n *\n * router.get(\n * {\n * path: \"/users/:id\",\n * openapi: {\n * summary: \"Get user by ID\",\n * tags: [\"Users\"]\n * }\n * },\n * (req, res) => { ... }\n * );\n *\n * @returns {IArkosRouter} A proxied Express Router instance with enhanced OpenAPI capabilities\n *\n * @see {@link ArkosRouteConfig} for configuration options\n */\nexport interface IArkosRouter extends IRouter {\n /** GET method handler with route configuration support */\n get: RouterMethodHandler<this>;\n /** POST method handler with route configuration support */\n post: RouterMethodHandler<this>;\n /** PUT method handler with route configuration support */\n put: RouterMethodHandler<this>;\n /** PATCH method handler with route configuration support */\n patch: RouterMethodHandler<this>;\n /** DELETE method handler with route configuration support */\n delete: RouterMethodHandler<this>;\n /** OPTIONS method handler with route configuration support */\n options: RouterMethodHandler<this>;\n /** HEAD method handler with route configuration support */\n head: RouterMethodHandler<this>;\n // /** TRACE method handler with route configuration support */\n trace: RouterMethodHandler<this>;\n /** ALL methods handler with route configuration support */\n all: RouterMethodHandler<this>;\n\n route<T extends string>(prefix: T): ArkosIRoute;\n route(prefix: PathParams): ArkosIRoute;\n}\n\n/**\n * Configuration object for defining routes in Arkos.js.\n */\nexport type ArkosRouteConfig = {\n /**\n * Disables the route by not mounting it internally.\n */\n disabled?: boolean;\n /**\n * The URL path pattern for the route.\n *\n * @example \"/api/users/:id\"\n */\n path: PathParams;\n /**\n * Authentication and authorization configuration.\n *\n * @remarks\n * - Set to `true` to require authentication without specific permissions.\n * - Set to `false` or omit to allow unauthenticated access.\n * - Provide an object to specify resource-based access control with resource name, action, and optional custom rules.\n */\n authentication?:\n | boolean\n | {\n resource: string;\n action: string;\n rule?: DetailedAccessControlRule | string[];\n };\n /**\n * Request validation configuration using Zod schemas or class constructors.\n *\n * @remarks\n * - Set to `false` to disable all validation.\n * - Provide an object with `query`, `body`, and/or `params` properties to validate specific parts of the request.\n * - Each property accepts a Zod schema, a class constructor, or `false` to disable validation for that part.\n */\n validation?:\n | false\n | {\n query?: ZodSchema | (new (...args: any[]) => object) | false;\n body?: ZodSchema | (new (...args: any[]) => object) | false;\n params?: ZodSchema | (new (...args: any[]) => object) | false;\n };\n\n /**\n * Rate limiting configuration for this route.\n *\n * @see {@link https://www.npmjs.com/package/express-rate-limit express-rate-limit} for available options.\n */\n rateLimit?: Partial<RateLimitOptions>;\n\n /**\n * Allows to define options for npm package compression.\n * Nothing is passed by default.\n *\n * @see {@link https://www.npmjs.com/package/compression compression} for further details.\n */\n compression?: compression.CompressionOptions;\n /**\n * Options to define how query must be parsed.\n *\n * @example\n * ```\n * GET /api/product?saleId=null\n * ```\n *\n * Normally would parsed to { saleId: \"null\" } so query parser\n * trough setting option `parseNull` will transform { saleId: null }\n *\n * @default\n * ```\n * {\n * parseNull: true,\n * parseUndefined: true,\n * parseBoolean: true,\n * }\n * ```\n *\n * @remarks\n * parseNumber may convert fields that are string but you only passed\n * numbers to query pay attention to this.\n *\n * Soon a feature to converted the query to the end prisma type will be added.\n */\n queryParser?: QueryParserOptions;\n /**\n * Configuration for request body parsing.\n *\n * @property {(\"json\" | \"urlencoded\" | \"raw\" | \"text\")} parser - The type of body parser to use.\n * @property {object} [options] - Parser-specific options passed to the corresponding Express body parser middleware.\n *\n * @remarks\n * - When `parser` is `\"json\"`, options are passed to `express.json()`.\n * - When `parser` is `\"urlencoded\"`, options are passed to `express.urlencoded()`.\n * - When `parser` is `\"raw\"`, options are passed to `express.raw()`.\n * - When `parser` is `\"text\"`, options are passed to `express.text()`.\n * - Set to `false` to disable body parsing for this route.\n *\n * @see {@link https://expressjs.com/en/api.html#express.json Express body parser documentation}\n */\n bodyParser?: BodyParserConfig | BodyParserConfig[] | false;\n /**\n * Experimental features to be battled tested before being stable\n *\n * PS: These features may be changed without any previous warning.\n */\n experimental?: {\n /**\n * OpenAPI specification for this route.\n *\n * @remarks\n * - Set to `false` to exclude this route from OpenAPI documentation.\n * - Provide a partial OpenAPI operation object to document the route.\n */\n openapi?: false | OpenApiConfig;\n /**\n * Configuration for file upload handling in routes.\n * Supports single file, multiple files from same field, or multiple fields with files.\n */\n uploads?: UploadConfig;\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/utils/arkos-router/types/index.ts"],"names":[],"mappings":"","sourcesContent":["import { IRoute, IRouter, Locals } from \"express\";\nimport { z, ZodSchema } from \"zod\";\nimport { Options as RateLimitOptions } from \"express-rate-limit\";\nimport { Options as QueryParserOptions } from \"../../../utils/helpers/query-parser.helpers\";\nimport { DetailedAccessControlRule } from \"../../../types/auth\";\nimport { ArkosErrorRequestHandler, ArkosRequestHandler } from \"../../../types\";\nimport compression from \"compression\";\nimport { OpenApiConfig } from \"./openapi-config\";\nimport { UploadConfig } from \"./upload-config\";\nimport { BodyParserConfig } from \"./body-parser-config\";\n\ntype InferValidationType<T, Fallback> = T extends ZodSchema\n ? z.infer<T>\n : T extends new (...args: any[]) => infer I\n ? I\n : Fallback;\n\nexport type PathParams = string | RegExp | Array<string | RegExp>;\n\nexport type ArkosAnyRequestHandler =\n | ArkosRequestHandler\n | ArkosErrorRequestHandler\n | Array<ArkosRequestHandler | ArkosErrorRequestHandler>;\n\n/**\n * Handler function for HTTP methods that accepts route configuration and request handlers.\n *\n * @param {ArkosRouteConfig} config - The route configuration object.\n * @param {...(ArkosRequestHandler | ArkosErrorRequestHandler)[]} handlers - Request and error handlers for the route.\n * @returns {IRouter} The Express router instance.\n */\ntype RouterMethodHandler<T> = {\n (config: PathParams, ...handlers: Array<ArkosAnyRequestHandler>): T;\n <\n TQuery extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TBody extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TParams extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n >(\n config: ArkosRouteConfig<TQuery, TBody, TParams> | PathParams,\n ...handlers: Array<\n | ArkosRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n any\n >\n | Array<\n ArkosRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n any\n >\n >\n >\n ): T;\n <\n TQuery extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TBody extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TParams extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n >(\n config: ArkosRouteConfig<TQuery, TBody, TParams> | PathParams,\n ...handlers: Array<\n | ArkosErrorRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n any\n >\n | Array<\n ArkosErrorRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n any\n >\n >\n >\n ): T;\n};\n\nexport type ArkosRouteMethodHandler<T> = {\n (\n config: ArkosAnyRequestHandler | Omit<ArkosRouteConfig, \"path\">,\n ...handlers: Array<\n | ArkosRequestHandler\n | ArkosErrorRequestHandler\n | Array<ArkosRequestHandler | ArkosErrorRequestHandler>\n >\n ): T;\n <\n TQuery extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TBody extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TParams extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n >(\n config: Omit<ArkosRouteConfig<TQuery, TBody, TParams>, \"path\">,\n ...handlers: Array<\n | ArkosRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n Locals\n >\n | Array<\n ArkosRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n Locals\n >\n >\n >\n ): T;\n\n <\n TQuery extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TBody extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TParams extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n >(\n config: Omit<ArkosRouteConfig<TQuery, TBody, TParams>, \"path\">,\n ...handlers: Array<\n | ArkosErrorRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n Locals\n >\n | Array<\n ArkosErrorRequestHandler<\n InferValidationType<TParams, Record<string, string>>,\n any,\n InferValidationType<TBody, any>,\n InferValidationType<TQuery, qs.ParsedQs>,\n Locals\n >\n >\n >\n ): T;\n};\n\nexport interface IArkosRoute extends IRoute {\n /** GET method handler with route configuration support */\n get: ArkosRouteMethodHandler<this>;\n /** POST method handler with route configuration support */\n post: ArkosRouteMethodHandler<this>;\n /** PUT method handler with route configuration support */\n put: ArkosRouteMethodHandler<this>;\n /** PATCH method handler with route configuration support */\n patch: ArkosRouteMethodHandler<this>;\n /** DELETE method handler with route configuration support */\n delete: ArkosRouteMethodHandler<this>;\n /** OPTIONS method handler with route configuration support */\n options: ArkosRouteMethodHandler<this>;\n /** HEAD method handler with route configuration support */\n head: ArkosRouteMethodHandler<this>;\n // /** TRACE method handler with route configuration support */\n trace: ArkosRouteMethodHandler<this>;\n /** ALL methods handler with route configuration support */\n all: ArkosRouteMethodHandler<this>;\n}\n\n/**\n * Creates an enhanced Express Router with features like OpenAPI documentation capabilities and smart data validation.\n *\n * The ArkosRouter extends the standard Express Router with the ability to\n * automatically capture OpenAPI metadata from route configurations.\n *\n * @example\n * const router = ArkosRouter();\n *\n * router.get(\n * {\n * path: \"/users/:id\",\n * openapi: {\n * summary: \"Get user by ID\",\n * tags: [\"Users\"]\n * }\n * },\n * (req, res) => { ... }\n * );\n *\n * @returns {IArkosRouter} A proxied Express Router instance with enhanced OpenAPI capabilities\n *\n * @see {@link ArkosRouteConfig} for configuration options\n */\nexport interface IArkosRouter extends IRouter {\n /** GET method handler with route configuration support */\n get: RouterMethodHandler<this>;\n /** POST method handler with route configuration support */\n post: RouterMethodHandler<this>;\n /** PUT method handler with route configuration support */\n put: RouterMethodHandler<this>;\n /** PATCH method handler with route configuration support */\n patch: RouterMethodHandler<this>;\n /** DELETE method handler with route configuration support */\n delete: RouterMethodHandler<this>;\n /** OPTIONS method handler with route configuration support */\n options: RouterMethodHandler<this>;\n /** HEAD method handler with route configuration support */\n head: RouterMethodHandler<this>;\n // /** TRACE method handler with route configuration support */\n trace: RouterMethodHandler<this>;\n /** ALL methods handler with route configuration support */\n all: RouterMethodHandler<this>;\n\n route<T extends string>(prefix: T): IArkosRoute;\n route(prefix: PathParams): IArkosRoute;\n}\n\n/**\n * Configuration object for defining routes in Arkos.js.\n */\nexport type ArkosRouteConfig<\n TQuery extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TBody extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n TParams extends\n | ZodSchema\n | (new (...args: any[]) => object)\n | false\n | undefined = any,\n> = {\n /**\n * Disables the route by not mounting it internally.\n */\n disabled?: boolean;\n /**\n * The URL path pattern for the route.\n *\n * @example \"/api/users/:id\"\n */\n path: PathParams;\n /**\n * Authentication and authorization configuration.\n *\n * @remarks\n * - Set to `true` to require authentication without specific permissions.\n * - Set to `false` or omit to allow unauthenticated access.\n * - Provide an object to specify resource-based access control with resource name, action, and optional custom rules.\n */\n authentication?:\n | boolean\n | {\n resource: string;\n action: string;\n rule?: DetailedAccessControlRule | string[];\n };\n /**\n * Request validation configuration using Zod schemas or class constructors.\n *\n * @remarks\n * - Set to `false` to disable all validation.\n * - Provide an object with `query`, `body`, and/or `params` properties to validate specific parts of the request.\n * - Each property accepts a Zod schema, a class constructor, or `false` to disable validation for that part.\n */\n validation?:\n | false\n | {\n query?: TQuery;\n body?: TBody;\n params?: TParams;\n };\n /**\n * Rate limiting configuration for this route.\n *\n * @see {@link https://www.npmjs.com/package/express-rate-limit express-rate-limit} for available options.\n */\n rateLimit?: Partial<RateLimitOptions>;\n\n /**\n * Allows to define options for npm package compression.\n * Nothing is passed by default.\n *\n * @see {@link https://www.npmjs.com/package/compression compression} for further details.\n */\n compression?: compression.CompressionOptions;\n /**\n * Options to define how query must be parsed.\n *\n * @example\n * ```\n * GET /api/product?saleId=null\n * ```\n *\n * Normally would parsed to { saleId: \"null\" } so query parser\n * trough setting option `parseNull` will transform { saleId: null }\n *\n * @default\n * ```\n * {\n * parseNull: true,\n * parseUndefined: true,\n * parseBoolean: true,\n * }\n * ```\n *\n * @remarks\n * parseNumber may convert fields that are string but you only passed\n * numbers to query pay attention to this.\n *\n * Soon a feature to converted the query to the end prisma type will be added.\n */\n queryParser?: QueryParserOptions;\n /**\n * Configuration for request body parsing.\n *\n * @property {(\"json\" | \"urlencoded\" | \"raw\" | \"text\")} parser - The type of body parser to use.\n * @property {object} [options] - Parser-specific options passed to the corresponding Express body parser middleware.\n *\n * @remarks\n * - When `parser` is `\"json\"`, options are passed to `express.json()`.\n * - When `parser` is `\"urlencoded\"`, options are passed to `express.urlencoded()`.\n * - When `parser` is `\"raw\"`, options are passed to `express.raw()`.\n * - When `parser` is `\"text\"`, options are passed to `express.text()`.\n * - Set to `false` to disable body parsing for this route.\n *\n * @see {@link https://expressjs.com/en/api.html#express.json Express body parser documentation}\n */\n bodyParser?: BodyParserConfig | BodyParserConfig[] | false;\n /**\n * Experimental features to be battled tested before being stable\n *\n * PS: These features may be changed without any previous warning.\n */\n experimental?: {\n /**\n * OpenAPI specification for this route.\n *\n * @remarks\n * - Set to `false` to exclude this route from OpenAPI documentation.\n * - Provide a partial OpenAPI operation object to document the route.\n */\n openapi?: false | OpenApiConfig;\n /**\n * Configuration for file upload handling in routes.\n * Supports single file, multiple files from same field, or multiple fields with files.\n */\n uploads?: UploadConfig;\n };\n};\n"]}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import RouteConfigValidator from "../../route-config-validator.js";
|
|
2
|
+
import { applyPrefix, getMiddlewareStack } from "./index.js";
|
|
3
|
+
import { getUserFileExtension } from "../../../helpers/fs.helpers.js";
|
|
4
|
+
import { getArkosConfig } from "../../../../server.js";
|
|
5
|
+
import RouteConfigRegistry from "../../route-config-registry.js";
|
|
6
|
+
import { catchAsync } from "../../../../exports/error-handler/index.js";
|
|
7
|
+
import deepmerge from "../../../helpers/deepmerge.helper.js";
|
|
8
|
+
import ExitError from "../../../helpers/exit-error.js";
|
|
9
|
+
import uploadManager from "./upload-manager.js";
|
|
10
|
+
export function applyArkosRouterProxy(target, options, name = "ArkosRouter()") {
|
|
11
|
+
return new Proxy(target, {
|
|
12
|
+
get(target, prop, receiver) {
|
|
13
|
+
const originalMethod = Reflect.get(target, prop, receiver);
|
|
14
|
+
const httpMethods = [
|
|
15
|
+
"get",
|
|
16
|
+
"post",
|
|
17
|
+
"put",
|
|
18
|
+
"patch",
|
|
19
|
+
"delete",
|
|
20
|
+
"all",
|
|
21
|
+
"head",
|
|
22
|
+
"trace",
|
|
23
|
+
"options",
|
|
24
|
+
];
|
|
25
|
+
if (prop === "use") {
|
|
26
|
+
return function (config, ...handlers) {
|
|
27
|
+
if (!config ||
|
|
28
|
+
typeof config !== "object" ||
|
|
29
|
+
Array.isArray(config) ||
|
|
30
|
+
typeof config === "function")
|
|
31
|
+
return originalMethod.call(target, config, ...handlers);
|
|
32
|
+
if (config.disabled)
|
|
33
|
+
return;
|
|
34
|
+
const useConfig = config;
|
|
35
|
+
const path = useConfig.path
|
|
36
|
+
? applyPrefix(options?.prefix, useConfig.path)
|
|
37
|
+
: undefined;
|
|
38
|
+
const arkosConfig = getArkosConfig();
|
|
39
|
+
const authenticationConfig = arkosConfig.authentication;
|
|
40
|
+
if (useConfig.authentication && !authenticationConfig?.mode)
|
|
41
|
+
throw ExitError(`Trying to authenticate route use${path ? ` ${path}` : ""} without choosing an authentication mode under arkos.config.${getUserFileExtension()}
|
|
42
|
+
|
|
43
|
+
For further help see https://www.arkosjs.com/docs/core-concepts/authentication/setup.`);
|
|
44
|
+
const middlewareStack = getMiddlewareStack(useConfig);
|
|
45
|
+
const allHandlers = [...middlewareStack, ...handlers];
|
|
46
|
+
return path
|
|
47
|
+
? originalMethod.call(target, path, ...allHandlers)
|
|
48
|
+
: originalMethod.call(target, ...allHandlers);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (prop === "route") {
|
|
52
|
+
return function (path) {
|
|
53
|
+
const routeChain = {};
|
|
54
|
+
httpMethods.forEach((method) => {
|
|
55
|
+
routeChain[method] = function (config, ...handlers) {
|
|
56
|
+
const fullConfig = {
|
|
57
|
+
...config,
|
|
58
|
+
...(options?.openapi
|
|
59
|
+
? {
|
|
60
|
+
experimental: {
|
|
61
|
+
openapi: options.openapi,
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
: {}),
|
|
65
|
+
path,
|
|
66
|
+
};
|
|
67
|
+
receiver[method](fullConfig, ...handlers);
|
|
68
|
+
return routeChain;
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
return routeChain;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (httpMethods.includes(prop)) {
|
|
75
|
+
return function (config, ...handlers) {
|
|
76
|
+
if (config.disabled)
|
|
77
|
+
return;
|
|
78
|
+
if (!RouteConfigValidator.isArkosRouteConfig(config))
|
|
79
|
+
throw Error(`First argument of ${name}.${prop}() must be a valid ArkosRouteConfig object with path field, but recevied ${typeof config === "object" ? JSON.stringify(config, null, 2) : config}`);
|
|
80
|
+
const path = applyPrefix(options?.prefix, config.path);
|
|
81
|
+
config = {
|
|
82
|
+
...config,
|
|
83
|
+
...(options?.openapi
|
|
84
|
+
? {
|
|
85
|
+
experimental: {
|
|
86
|
+
...config?.experimental,
|
|
87
|
+
openapi: deepmerge(options.openapi || {}, config?.experimental?.openapi || {}),
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
: {}),
|
|
91
|
+
path,
|
|
92
|
+
};
|
|
93
|
+
if ([null, undefined].includes(path))
|
|
94
|
+
throw Error("Please pass valid value for path field to use in your route");
|
|
95
|
+
const method = prop;
|
|
96
|
+
const UndefinedHandlerError = (handler) => Error(`Wrong value for handler in route ${method.toUpperCase()} ${path}, recevied ${handler}.`);
|
|
97
|
+
if (handlers.length > 0) {
|
|
98
|
+
const flattenHandlers = (arr) => {
|
|
99
|
+
return arr.reduce((flat, item) => {
|
|
100
|
+
return flat.concat(Array.isArray(item) ? flattenHandlers(item) : item);
|
|
101
|
+
}, []);
|
|
102
|
+
};
|
|
103
|
+
const flatHandlers = flattenHandlers(handlers);
|
|
104
|
+
handlers = flatHandlers.map((handler) => {
|
|
105
|
+
if (!handler)
|
|
106
|
+
throw UndefinedHandlerError(handler);
|
|
107
|
+
if (typeof handler !== "function") {
|
|
108
|
+
throw UndefinedHandlerError(handler);
|
|
109
|
+
}
|
|
110
|
+
return catchAsync(handler, {
|
|
111
|
+
type: handler.length > 3 ? "error" : "normal",
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
const finalHandler = handlers[handlers.length - 1];
|
|
115
|
+
RouteConfigRegistry.register(finalHandler, config, method);
|
|
116
|
+
}
|
|
117
|
+
const arkosConfig = getArkosConfig();
|
|
118
|
+
const validationConfig = arkosConfig.validation;
|
|
119
|
+
const authenticationConfig = arkosConfig.authentication;
|
|
120
|
+
const strictValidation = validationConfig?.strict;
|
|
121
|
+
const route = `${method.toUpperCase()} ${path}`;
|
|
122
|
+
if (strictValidation &&
|
|
123
|
+
(!("validation" in config) ||
|
|
124
|
+
("validation" in config &&
|
|
125
|
+
!config.validation &&
|
|
126
|
+
config.validation !== undefined)))
|
|
127
|
+
throw Error("When using strict validation you must either pass { validation: false } in order to explicitly tell that no input will be received, or pass `undefined` for each input type e.g { validation: { query: undefined } } in order to deny the input of given request input.");
|
|
128
|
+
if (!validationConfig?.resolver &&
|
|
129
|
+
Object.keys(config.validation || {}).length > 0)
|
|
130
|
+
throw Error(`Trying to pass validators into route ${route} config validation option without choosing a validation resolver under arkos.init({ validation: { resolver: '' } })`);
|
|
131
|
+
if (config.authentication && !authenticationConfig?.mode)
|
|
132
|
+
throw Error(`Trying to authenticate route ${route} without choosing an authentication mode under arkos.config.${getUserFileExtension()}
|
|
133
|
+
|
|
134
|
+
For further help see https://www.arkosjs.com/docs/core-concepts/authentication-system.`);
|
|
135
|
+
handlers = [...getMiddlewareStack(config), ...handlers];
|
|
136
|
+
if (config.experimental?.uploads &&
|
|
137
|
+
config.experimental.uploads.deleteOnError !== false)
|
|
138
|
+
handlers.push(catchAsync(uploadManager.handleFileCleanup(config.experimental.uploads), { type: "error" }));
|
|
139
|
+
return originalMethod.call(target, path, ...handlers);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return originalMethod;
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=apply-arkos-router-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-arkos-router-proxy.js","sourceRoot":"","sources":["../../../../../../src/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.ts"],"names":[],"mappings":"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","sourcesContent":["import { RouterOptions } from \"express\";\nimport {\n ArkosAnyRequestHandler,\n ArkosRouteConfig,\n ArkosUseConfig,\n IArkosRoute,\n PathParams,\n} from \"../../types\";\nimport RouteConfigValidator from \"../../route-config-validator\";\nimport { applyPrefix, getMiddlewareStack } from \".\";\nimport { getUserFileExtension } from \"../../../helpers/fs.helpers\";\nimport { getArkosConfig } from \"../../../../server\";\nimport RouteConfigRegistry from \"../../route-config-registry\";\nimport { catchAsync } from \"../../../../exports/error-handler\";\nimport deepmerge from \"../../../helpers/deepmerge.helper\";\nimport ExitError from \"../../../helpers/exit-error\";\nimport uploadManager from \"./upload-manager\";\n\nexport function applyArkosRouterProxy<T extends object>(\n target: T,\n options?: RouterOptions & {\n prefix?: string | RegExp | Array<string | RegExp>;\n openapi?: { tags?: string[] };\n },\n name: \"app\" | \"ArkosRouter()\" = \"ArkosRouter()\"\n): T {\n return new Proxy(target, {\n get(target, prop, receiver) {\n const originalMethod = Reflect.get(target, prop, receiver) as Function;\n\n const httpMethods = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"all\",\n \"head\",\n \"trace\",\n \"options\",\n ] as const;\n\n if (prop === \"use\") {\n return function (\n config: ArkosUseConfig | PathParams | ArkosAnyRequestHandler,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n // if not an ArkosUseConfig object, fall through to native Express use\n if (\n !config ||\n typeof config !== \"object\" ||\n Array.isArray(config) ||\n typeof config === \"function\"\n )\n return originalMethod.call(target, config, ...handlers);\n\n if ((config as ArkosUseConfig).disabled) return;\n\n const useConfig = config as ArkosUseConfig;\n const path = useConfig.path\n ? applyPrefix(options?.prefix, useConfig.path)\n : undefined;\n\n const arkosConfig = getArkosConfig();\n const authenticationConfig = arkosConfig.authentication;\n\n if (useConfig.authentication && !authenticationConfig?.mode)\n throw ExitError(\n `Trying to authenticate route use${path ? ` ${path}` : \"\"} without choosing an authentication mode under arkos.config.${getUserFileExtension()}\n\nFor further help see https://www.arkosjs.com/docs/core-concepts/authentication/setup.`\n );\n\n const middlewareStack = getMiddlewareStack(useConfig);\n\n const allHandlers = [...middlewareStack, ...handlers];\n\n return path\n ? originalMethod.call(target, path, ...allHandlers)\n : originalMethod.call(target, ...allHandlers);\n };\n }\n\n if (prop === \"route\") {\n return function (path: PathParams) {\n const routeChain: any = {};\n\n httpMethods.forEach((method) => {\n routeChain[method] = function (\n config: ArkosAnyRequestHandler | Omit<ArkosRouteConfig, \"path\">,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n const fullConfig: ArkosRouteConfig = {\n ...config,\n ...(options?.openapi\n ? {\n experimental: {\n openapi: options.openapi,\n },\n }\n : {}),\n path,\n };\n\n receiver[method](fullConfig, ...handlers);\n\n return routeChain as IArkosRoute;\n };\n });\n\n return routeChain;\n };\n }\n\n if (httpMethods.includes(prop as any)) {\n return function (\n config: ArkosRouteConfig,\n ...handlers: ArkosAnyRequestHandler[]\n ) {\n if (config.disabled) return;\n\n if (!RouteConfigValidator.isArkosRouteConfig(config))\n throw Error(\n `First argument of ${name}.${prop as string}() must be a valid ArkosRouteConfig object with path field, but recevied ${typeof config === \"object\" ? JSON.stringify(config, null, 2) : config}`\n );\n\n const path = applyPrefix(options?.prefix, config.path);\n\n config = {\n ...config,\n ...(options?.openapi\n ? {\n experimental: {\n ...config?.experimental,\n openapi: deepmerge(\n options.openapi || {},\n config?.experimental?.openapi || {}\n ),\n },\n }\n : {}),\n path,\n };\n\n if ([null, undefined].includes(path as any))\n throw Error(\n \"Please pass valid value for path field to use in your route\"\n );\n\n const method = prop as string;\n const UndefinedHandlerError = (handler: any) =>\n Error(\n `Wrong value for handler in route ${method.toUpperCase()} ${path}, recevied ${handler}.`\n );\n\n if (handlers.length > 0) {\n const flattenHandlers = (arr: any[]): ArkosAnyRequestHandler[] => {\n return arr.reduce((flat, item) => {\n return flat.concat(\n Array.isArray(item) ? flattenHandlers(item) : item\n );\n }, []);\n };\n\n const flatHandlers = flattenHandlers(handlers);\n\n handlers = flatHandlers.map((handler: ArkosAnyRequestHandler) => {\n if (!handler) throw UndefinedHandlerError(handler);\n\n if (typeof handler !== \"function\") {\n throw UndefinedHandlerError(handler);\n }\n\n return catchAsync(handler, {\n type: handler.length > 3 ? \"error\" : \"normal\",\n });\n });\n\n const finalHandler = handlers[handlers.length - 1];\n RouteConfigRegistry.register(finalHandler, config, method);\n }\n\n const arkosConfig = getArkosConfig();\n const validationConfig = arkosConfig.validation;\n const authenticationConfig = arkosConfig.authentication;\n const strictValidation = validationConfig?.strict;\n const route = `${method.toUpperCase()} ${path}`;\n\n if (\n strictValidation &&\n (!(\"validation\" in config) ||\n (\"validation\" in config &&\n !config.validation &&\n config.validation !== undefined))\n )\n throw Error(\n \"When using strict validation you must either pass { validation: false } in order to explicitly tell that no input will be received, or pass `undefined` for each input type e.g { validation: { query: undefined } } in order to deny the input of given request input.\"\n );\n\n if (\n !validationConfig?.resolver &&\n Object.keys(config.validation || {}).length > 0\n )\n throw Error(\n `Trying to pass validators into route ${route} config validation option without choosing a validation resolver under arkos.init({ validation: { resolver: '' } })`\n );\n\n if (config.authentication && !authenticationConfig?.mode)\n throw Error(\n `Trying to authenticate route ${route} without choosing an authentication mode under arkos.config.${getUserFileExtension()}\n\nFor further help see https://www.arkosjs.com/docs/core-concepts/authentication-system.`\n );\n\n handlers = [...getMiddlewareStack(config), ...handlers];\n\n if (\n config.experimental?.uploads &&\n config.experimental.uploads.deleteOnError !== false\n )\n handlers.push(\n catchAsync(\n uploadManager.handleFileCleanup(config.experimental.uploads),\n { type: \"error\" }\n )\n );\n\n return originalMethod.call(target, path, ...handlers);\n };\n }\n // }\n return originalMethod;\n },\n });\n}\n"]}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export class Bundler {
|
|
4
|
+
compileAliases(resolvedPaths) {
|
|
5
|
+
return Object.entries(resolvedPaths.paths).map(([pattern, targets]) => {
|
|
6
|
+
const isWildcard = pattern.endsWith("/*");
|
|
7
|
+
return {
|
|
8
|
+
prefix: isWildcard ? pattern.slice(0, -2) : pattern,
|
|
9
|
+
isWildcard,
|
|
10
|
+
targets,
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
loadConfig(rootDir, configPath) {
|
|
15
|
+
const resolved = configPath
|
|
16
|
+
? path.resolve(configPath)
|
|
17
|
+
: this.findConfig(rootDir);
|
|
18
|
+
if (!resolved || !fs.existsSync(resolved)) {
|
|
19
|
+
return { baseUrl: rootDir, paths: {} };
|
|
20
|
+
}
|
|
21
|
+
return this.parseConfig(resolved, rootDir);
|
|
22
|
+
}
|
|
23
|
+
findConfig(dir) {
|
|
24
|
+
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
25
|
+
const candidate = path.join(dir, name);
|
|
26
|
+
if (fs.existsSync(candidate))
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
parseConfig(configPath, rootDir) {
|
|
32
|
+
const configDir = path.dirname(configPath);
|
|
33
|
+
const raw = this.readJsonWithComments(configPath);
|
|
34
|
+
let base = { baseUrl: rootDir, paths: {} };
|
|
35
|
+
if (raw.extends) {
|
|
36
|
+
const isPackage = !raw.extends.startsWith(".");
|
|
37
|
+
const parentPath = isPackage
|
|
38
|
+
? this.resolveNodeModulesConfig(raw.extends, rootDir)
|
|
39
|
+
: path.resolve(configDir, raw.extends);
|
|
40
|
+
if (parentPath && fs.existsSync(parentPath)) {
|
|
41
|
+
base = this.parseConfig(parentPath, rootDir);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const co = raw.compilerOptions || {};
|
|
45
|
+
const baseUrl = co.baseUrl
|
|
46
|
+
? path.resolve(configDir, co.baseUrl)
|
|
47
|
+
: base.baseUrl;
|
|
48
|
+
return {
|
|
49
|
+
baseUrl,
|
|
50
|
+
paths: { ...base.paths, ...(co.paths || {}) },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
resolveNodeModulesConfig(extendsValue, rootDir) {
|
|
54
|
+
try {
|
|
55
|
+
return require.resolve(extendsValue, { paths: [rootDir] });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
readJsonWithComments(filePath) {
|
|
62
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
63
|
+
return JSON.parse(raw
|
|
64
|
+
.replace(/("(?:[^"\\]|\\.)*")|\/\/[^\n]*|\/\*[\s\S]*?\*\//g, (_, str) => str ?? "")
|
|
65
|
+
.replace(/,(\s*[}\]])/g, "$1"));
|
|
66
|
+
}
|
|
67
|
+
resolveImport(importPath, fileDir, rootOutDir, rootDir, ext, resolvedPaths, compiledAliases) {
|
|
68
|
+
if (importPath.startsWith(".") || importPath.startsWith("/")) {
|
|
69
|
+
return this.addExtension(importPath, fileDir, ext);
|
|
70
|
+
}
|
|
71
|
+
for (const alias of compiledAliases) {
|
|
72
|
+
if (alias.isWildcard) {
|
|
73
|
+
if (!importPath.startsWith(alias.prefix + "/"))
|
|
74
|
+
continue;
|
|
75
|
+
const remainder = importPath.slice(alias.prefix.length + 1);
|
|
76
|
+
for (const target of alias.targets) {
|
|
77
|
+
const absoluteSource = path.resolve(resolvedPaths.baseUrl, target.replace("*", remainder));
|
|
78
|
+
const fileDirInSource = this.getFileDirInSource(fileDir, rootOutDir, rootDir, resolvedPaths.baseUrl);
|
|
79
|
+
return this.addExtension(this.toRelative(fileDirInSource, absoluteSource), fileDir, ext);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (importPath !== alias.prefix)
|
|
84
|
+
continue;
|
|
85
|
+
for (const target of alias.targets) {
|
|
86
|
+
const absoluteSource = path.resolve(resolvedPaths.baseUrl, target);
|
|
87
|
+
const fileDirInSource = this.getFileDirInSource(fileDir, rootOutDir, rootDir, resolvedPaths.baseUrl);
|
|
88
|
+
return this.addExtension(this.toRelative(fileDirInSource, absoluteSource), fileDir, ext);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return importPath;
|
|
93
|
+
}
|
|
94
|
+
getFileDirInSource(fileDir, rootOutDir, rootDir, baseUrl) {
|
|
95
|
+
const relToRootDir = path.relative(rootDir, rootOutDir);
|
|
96
|
+
if (!relToRootDir)
|
|
97
|
+
return baseUrl;
|
|
98
|
+
const distFolderName = relToRootDir.split(path.sep)[0];
|
|
99
|
+
const distRoot = path.join(rootDir, distFolderName);
|
|
100
|
+
const relFromDistRoot = path.relative(distRoot, fileDir);
|
|
101
|
+
return path.resolve(baseUrl, relFromDistRoot);
|
|
102
|
+
}
|
|
103
|
+
addExtension(importPath, fileDir, ext) {
|
|
104
|
+
if (importPath.endsWith(ext))
|
|
105
|
+
return importPath;
|
|
106
|
+
const absolute = path.resolve(fileDir, importPath);
|
|
107
|
+
if (fs.existsSync(absolute + "/index" + ext)) {
|
|
108
|
+
return importPath + "/index" + ext;
|
|
109
|
+
}
|
|
110
|
+
return importPath + ext;
|
|
111
|
+
}
|
|
112
|
+
toRelative(fromDir, toPath) {
|
|
113
|
+
const rel = path.relative(fromDir, toPath).replace(/\\/g, "/");
|
|
114
|
+
return rel.startsWith(".") ? rel : "./" + rel;
|
|
115
|
+
}
|
|
116
|
+
rewriteImports(content, fileDir, rootOutDir, rootDir, ext, resolvedPaths, compiledAliases) {
|
|
117
|
+
for (const regex of Bundler.IMPORT_REGEXES) {
|
|
118
|
+
regex.lastIndex = 0;
|
|
119
|
+
content = content.replace(regex, (match, p) => {
|
|
120
|
+
const fixed = this.resolveImport(p, fileDir, rootOutDir, rootDir, ext, resolvedPaths, compiledAliases);
|
|
121
|
+
return fixed === p ? match : match.replace(p, fixed);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return content;
|
|
125
|
+
}
|
|
126
|
+
bundle(options) {
|
|
127
|
+
const rootDir = path.resolve(options.rootDir || process.cwd());
|
|
128
|
+
const outDir = path.resolve(options.outDir);
|
|
129
|
+
const resolvedPaths = this.loadConfig(rootDir, options.configPath);
|
|
130
|
+
const compiledAliases = this.compileAliases(resolvedPaths);
|
|
131
|
+
this._bundleDir(options.ext, outDir, rootDir, resolvedPaths, compiledAliases, outDir);
|
|
132
|
+
}
|
|
133
|
+
_bundleDir(ext, rootOutDir, rootDir, resolvedPaths, compiledAliases, dir) {
|
|
134
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
const fullPath = path.join(dir, entry.name);
|
|
137
|
+
if (entry.isDirectory()) {
|
|
138
|
+
this._bundleDir(ext, rootOutDir, rootDir, resolvedPaths, compiledAliases, fullPath);
|
|
139
|
+
}
|
|
140
|
+
else if (/\.(js|cjs|mjs)$/.test(entry.name)) {
|
|
141
|
+
const content = fs.readFileSync(fullPath, "utf8");
|
|
142
|
+
const updated = this.rewriteImports(content, path.dirname(fullPath), rootOutDir, rootDir, ext, resolvedPaths, compiledAliases);
|
|
143
|
+
if (updated !== content)
|
|
144
|
+
fs.writeFileSync(fullPath, updated);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
Bundler.IMPORT_REGEXES = [
|
|
150
|
+
/from\s+['"]([^'"]+)['"]/g,
|
|
151
|
+
/import\s+['"]([^'"]+)['"]/g,
|
|
152
|
+
/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
153
|
+
/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
154
|
+
];
|
|
155
|
+
export const bundler = new Bundler();
|
|
156
|
+
//# sourceMappingURL=bundler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../../../src/utils/bundler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AA8DxB,MAAM,OAAO,OAAO;IAiBV,cAAc,CAAC,aAA4B;QACjD,OAAO,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE;YACpE,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO;gBACL,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;gBACnD,UAAU;gBACV,OAAO;aACR,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IASO,UAAU,CAAC,OAAe,EAAE,UAAmB;QACrD,MAAM,QAAQ,GAAG,UAAU;YACzB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAE7B,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACzC,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IASO,UAAU,CAAC,GAAW;QAC5B,KAAK,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC;YACtD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACvC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IASO,WAAW,CAAC,UAAkB,EAAE,OAAe;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAElD,IAAI,IAAI,GAAkB,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAE1D,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,SAAS;gBAC1B,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;gBACrD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAEzC,IAAI,UAAU,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5C,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,MAAM,EAAE,GAAG,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO;YACxB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC;YACrC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAEjB,OAAO;YACL,OAAO;YACP,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;SAC9C,CAAC;IACJ,CAAC;IAUO,wBAAwB,CAC9B,YAAoB,EACpB,OAAe;QAEf,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IASO,oBAAoB,CAAC,QAAgB;QAC3C,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CACf,GAAG;aACA,OAAO,CACN,kDAAkD,EAClD,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CACtB;aACA,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CACjC,CAAC;IACJ,CAAC;IAiBO,aAAa,CACnB,UAAkB,EAClB,OAAe,EACf,UAAkB,EAClB,OAAe,EACf,GAAW,EACX,aAA4B,EAC5B,eAAgC;QAEhC,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7D,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACrD,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;oBAAE,SAAS;gBACzD,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAE5D,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CACjC,aAAa,CAAC,OAAO,EACrB,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAC/B,CAAC;oBACF,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAC7C,OAAO,EACP,UAAU,EACV,OAAO,EACP,aAAa,CAAC,OAAO,CACtB,CAAC;oBACF,OAAO,IAAI,CAAC,YAAY,CACtB,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAChD,OAAO,EACP,GAAG,CACJ,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,UAAU,KAAK,KAAK,CAAC,MAAM;oBAAE,SAAS;gBAC1C,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBACnE,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAC7C,OAAO,EACP,UAAU,EACV,OAAO,EACP,aAAa,CAAC,OAAO,CACtB,CAAC;oBACF,OAAO,IAAI,CAAC,YAAY,CACtB,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAChD,OAAO,EACP,GAAG,CACJ,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAEO,kBAAkB,CACxB,OAAe,EACf,UAAkB,EAClB,OAAe,EACf,OAAe;QAEf,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACxD,IAAI,CAAC,YAAY;YAAE,OAAO,OAAO,CAAC;QAGlC,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACpD,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAChD,CAAC;IAWO,YAAY,CAClB,UAAkB,EAClB,OAAe,EACf,GAAW;QAEX,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QAEhD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACnD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,GAAG,QAAQ,GAAG,GAAG,CAAC,EAAE,CAAC;YAC7C,OAAO,UAAU,GAAG,QAAQ,GAAG,GAAG,CAAC;QACrC,CAAC;QAED,OAAO,UAAU,GAAG,GAAG,CAAC;IAC1B,CAAC;IAUO,UAAU,CAAC,OAAe,EAAE,MAAc;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/D,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;IAChD,CAAC;IAYO,cAAc,CACpB,OAAe,EACf,OAAe,EACf,UAAkB,EAClB,OAAe,EACf,GAAW,EACX,aAA4B,EAC5B,eAAgC;QAEhC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3C,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAC9B,CAAC,EACD,OAAO,EACP,UAAU,EACV,OAAO,EACP,GAAG,EACH,aAAa,EACb,eAAe,CAChB,CAAC;gBACF,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACvD,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IASD,MAAM,CAAC,OAAuB;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACnE,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAE3D,IAAI,CAAC,UAAU,CACb,OAAO,CAAC,GAAG,EACX,MAAM,EACN,OAAO,EACP,aAAa,EACb,eAAe,EACf,MAAM,CACP,CAAC;IACJ,CAAC;IAMO,UAAU,CAChB,GAAW,EACX,UAAkB,EAClB,OAAe,EACf,aAA4B,EAC5B,eAAgC,EAChC,GAAW;QAEX,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAE5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,UAAU,CACb,GAAG,EACH,UAAU,EACV,OAAO,EACP,aAAa,EACb,eAAe,EACf,QAAQ,CACT,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAClD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CACjC,OAAO,EACP,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EACtB,UAAU,EACV,OAAO,EACP,GAAG,EACH,aAAa,EACb,eAAe,CAChB,CAAC;gBACF,IAAI,OAAO,KAAK,OAAO;oBAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;;AAnWuB,sBAAc,GAAG;IACvC,0BAA0B;IAC1B,4BAA4B;IAC5B,sCAAsC;IACtC,uCAAuC;CACxC,CAAC;AAiWJ,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\n/**\n * Options for configuring a bundle run.\n */\ninterface BundlerOptions {\n /** Output file extension: \".js\" | \".cjs\" | \".mjs\" */\n ext: string;\n /** Directory containing the compiled output files to process */\n outDir: string;\n /** Source root directory used to resolve tsconfig paths. Defaults to process.cwd() */\n rootDir?: string;\n /** Explicit path to tsconfig.json or jsconfig.json. Auto-detected from rootDir if omitted */\n configPath?: string;\n}\n\n/**\n * Resolved path aliases and base URL extracted from tsconfig/jsconfig.\n */\ninterface ResolvedPaths {\n /** Absolute path used as the base for resolving alias targets */\n baseUrl: string;\n /** Map of alias patterns to their target path arrays, e.g. { \"@/*\": [\"src/*\"] } */\n paths: Record<string, string[]>;\n}\n\n/**\n * A pre-compiled alias entry for efficient matching at runtime.\n */\ninterface CompiledAlias {\n /** The alias prefix, e.g. \"@\" for \"@/*\" or \"@utils\" for \"@utils/*\" */\n prefix: string;\n /** Whether the alias uses a wildcard, e.g. \"@/*\" vs \"@root\" */\n isWildcard: boolean;\n /** Ordered list of target paths to try when the alias matches */\n targets: string[];\n}\n\n/**\n * Post-compilation import rewriter and alias resolver.\n *\n * Recursively processes all `.js`, `.cjs`, and `.mjs` files in the output\n * directory, rewriting:\n * - Relative imports to include the correct file extension\n * - Directory imports to use `/index.ext`\n * - Path aliases defined in tsconfig/jsconfig `paths` to relative paths\n *\n * Bare node_modules specifiers (e.g. `\"express\"`, `\"@prisma/client\"`) are\n * left untouched.\n *\n * @example\n * ```ts\n * const bundler = new Bundler();\n *\n * bundler.bundle({\n * ext: \".js\",\n * outDir: \"./dist\",\n * rootDir: \"./\",\n * configPath: \"./tsconfig.json\",\n * });\n * ```\n */\nexport class Bundler {\n /**\n * Regexes for matching all import/export/require statement forms.\n * Defined as static to avoid recreation per file processed.\n */\n private static readonly IMPORT_REGEXES = [\n /from\\s+['\"]([^'\"]+)['\"]/g,\n /import\\s+['\"]([^'\"]+)['\"]/g,\n /import\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g,\n /require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g,\n ];\n\n /**\n * Pre-compiles path alias patterns into a lookup-friendly structure\n * so alias matching during processing is O(n) over aliases rather than\n * re-parsing patterns per import.\n */\n private compileAliases(resolvedPaths: ResolvedPaths): CompiledAlias[] {\n return Object.entries(resolvedPaths.paths).map(([pattern, targets]) => {\n const isWildcard = pattern.endsWith(\"/*\");\n return {\n prefix: isWildcard ? pattern.slice(0, -2) : pattern,\n isWildcard,\n targets,\n };\n });\n }\n\n /**\n * Loads and parses the tsconfig/jsconfig file, resolving any `extends` chain.\n * Falls back to `{ baseUrl: rootDir, paths: {} }` if no config is found.\n *\n * @param rootDir - Absolute root directory\n * @param configPath - Explicit config path, or undefined to auto-detect\n */\n private loadConfig(rootDir: string, configPath?: string): ResolvedPaths {\n const resolved = configPath\n ? path.resolve(configPath)\n : this.findConfig(rootDir);\n\n if (!resolved || !fs.existsSync(resolved)) {\n return { baseUrl: rootDir, paths: {} };\n }\n\n return this.parseConfig(resolved, rootDir);\n }\n\n /**\n * Searches for a tsconfig.json or jsconfig.json in the given directory.\n * Prefers tsconfig.json over jsconfig.json.\n *\n * @param dir - Directory to search in\n * @returns Absolute path to the config file, or null if not found\n */\n private findConfig(dir: string): string | null {\n for (const name of [\"tsconfig.json\", \"jsconfig.json\"]) {\n const candidate = path.join(dir, name);\n if (fs.existsSync(candidate)) return candidate;\n }\n return null;\n }\n\n /**\n * Recursively parses a tsconfig/jsconfig file, following `extends` chains\n * and merging `paths` with child config taking precedence over parent.\n *\n * @param configPath - Absolute path to the config file to parse\n * @param rootDir - Absolute root directory used as fallback baseUrl\n */\n private parseConfig(configPath: string, rootDir: string): ResolvedPaths {\n const configDir = path.dirname(configPath);\n const raw = this.readJsonWithComments(configPath);\n\n let base: ResolvedPaths = { baseUrl: rootDir, paths: {} };\n\n if (raw.extends) {\n const isPackage = !raw.extends.startsWith(\".\");\n const parentPath = isPackage\n ? this.resolveNodeModulesConfig(raw.extends, rootDir)\n : path.resolve(configDir, raw.extends);\n\n if (parentPath && fs.existsSync(parentPath)) {\n base = this.parseConfig(parentPath, rootDir);\n }\n }\n\n const co = raw.compilerOptions || {};\n const baseUrl = co.baseUrl\n ? path.resolve(configDir, co.baseUrl)\n : base.baseUrl;\n\n return {\n baseUrl,\n paths: { ...base.paths, ...(co.paths || {}) },\n };\n }\n\n /**\n * Resolves a tsconfig `extends` value that points to a node_modules package,\n * e.g. `\"@tsconfig/node18/tsconfig.json\"`.\n *\n * @param extendsValue - The raw extends string from tsconfig\n * @param rootDir - Root directory to resolve from\n * @returns Absolute path to the resolved config file, or null if not found\n */\n private resolveNodeModulesConfig(\n extendsValue: string,\n rootDir: string\n ): string | null {\n try {\n return require.resolve(extendsValue, { paths: [rootDir] });\n } catch {\n return null;\n }\n }\n\n /**\n * Reads a JSON file that may contain comments and trailing commas\n * (as tsconfig/jsconfig files allow) and returns the parsed object.\n *\n * @param filePath - Absolute path to the JSON file\n * @returns Parsed object, or empty object if parsing fails\n */\n private readJsonWithComments(filePath: string): any {\n const raw = fs.readFileSync(filePath, \"utf8\");\n return JSON.parse(\n raw\n .replace(\n /(\"(?:[^\"\\\\]|\\\\.)*\")|\\/\\/[^\\n]*|\\/\\*[\\s\\S]*?\\*\\//g,\n (_, str) => str ?? \"\"\n )\n .replace(/,(\\s*[}\\]])/g, \"$1\")\n );\n }\n\n /**\n * Resolves a single import path to its final rewritten form.\n *\n * Resolution order:\n * 1. Relative imports (`./`, `../`) — extension is added via `addExtension`\n * 2. Aliased imports — matched against compiled aliases and converted to relative paths\n * 3. Bare specifiers (`express`, `@prisma/client`) — returned untouched\n *\n * @param importPath - The raw import string from source code\n * @param fileDir - Absolute directory of the file containing the import\n * @param ext - The output file extension\n * @param resolvedPaths - Resolved baseUrl and paths from tsconfig\n * @param compiledAliases - Pre-compiled alias entries\n */\n\n private resolveImport(\n importPath: string,\n fileDir: string,\n rootOutDir: string,\n rootDir: string,\n ext: string,\n resolvedPaths: ResolvedPaths,\n compiledAliases: CompiledAlias[]\n ): string {\n if (importPath.startsWith(\".\") || importPath.startsWith(\"/\")) {\n return this.addExtension(importPath, fileDir, ext);\n }\n\n for (const alias of compiledAliases) {\n if (alias.isWildcard) {\n if (!importPath.startsWith(alias.prefix + \"/\")) continue;\n const remainder = importPath.slice(alias.prefix.length + 1);\n\n for (const target of alias.targets) {\n const absoluteSource = path.resolve(\n resolvedPaths.baseUrl,\n target.replace(\"*\", remainder)\n );\n const fileDirInSource = this.getFileDirInSource(\n fileDir,\n rootOutDir,\n rootDir,\n resolvedPaths.baseUrl\n );\n return this.addExtension(\n this.toRelative(fileDirInSource, absoluteSource),\n fileDir,\n ext\n );\n }\n } else {\n if (importPath !== alias.prefix) continue;\n for (const target of alias.targets) {\n const absoluteSource = path.resolve(resolvedPaths.baseUrl, target);\n const fileDirInSource = this.getFileDirInSource(\n fileDir,\n rootOutDir,\n rootDir,\n resolvedPaths.baseUrl\n );\n return this.addExtension(\n this.toRelative(fileDirInSource, absoluteSource),\n fileDir,\n ext\n );\n }\n }\n }\n\n return importPath;\n }\n\n private getFileDirInSource(\n fileDir: string,\n rootOutDir: string,\n rootDir: string,\n baseUrl: string\n ): string {\n const relToRootDir = path.relative(rootDir, rootOutDir);\n if (!relToRootDir) return baseUrl;\n\n // First component of relToRootDir is the dist folder name (e.g. \"dist\")\n const distFolderName = relToRootDir.split(path.sep)[0];\n const distRoot = path.join(rootDir, distFolderName);\n const relFromDistRoot = path.relative(distRoot, fileDir);\n return path.resolve(baseUrl, relFromDistRoot);\n }\n\n /**\n * Appends the configured extension to an import path if not already present.\n * If the path resolves to a directory containing an `index` file, appends\n * `/index.ext` instead.\n *\n * @param importPath - The relative import path to fix\n * @param fileDir - Absolute directory of the file containing the import\n * @param ext - The output file extension\n */\n private addExtension(\n importPath: string,\n fileDir: string,\n ext: string\n ): string {\n if (importPath.endsWith(ext)) return importPath;\n\n const absolute = path.resolve(fileDir, importPath);\n if (fs.existsSync(absolute + \"/index\" + ext)) {\n return importPath + \"/index\" + ext;\n }\n\n return importPath + ext;\n }\n\n /**\n * Converts an absolute path to a relative path from a given directory,\n * ensuring the result always starts with `./` or `../`.\n *\n * @param fromDir - The directory to compute the relative path from\n * @param toPath - The absolute target path\n * @returns A POSIX-style relative path\n */\n private toRelative(fromDir: string, toPath: string): string {\n const rel = path.relative(fromDir, toPath).replace(/\\\\/g, \"/\");\n return rel.startsWith(\".\") ? rel : \"./\" + rel;\n }\n\n /**\n * Rewrites all import/export/require statements in a string of JS source code.\n * Each regex is reset before use since they are stateful with the `/g` flag.\n *\n * @param content - Raw file content to process\n * @param fileDir - Absolute directory of the file being processed\n * @param ext - The output file extension\n * @param resolvedPaths - Resolved baseUrl and paths from tsconfig\n * @param compiledAliases - Pre-compiled alias entries\n */\n private rewriteImports(\n content: string,\n fileDir: string,\n rootOutDir: string,\n rootDir: string,\n ext: string,\n resolvedPaths: ResolvedPaths,\n compiledAliases: CompiledAlias[]\n ): string {\n for (const regex of Bundler.IMPORT_REGEXES) {\n regex.lastIndex = 0;\n content = content.replace(regex, (match, p) => {\n const fixed = this.resolveImport(\n p,\n fileDir,\n rootOutDir,\n rootDir,\n ext,\n resolvedPaths,\n compiledAliases\n );\n return fixed === p ? match : match.replace(p, fixed);\n });\n }\n return content;\n }\n\n /**\n * Recursively processes all `.js`, `.cjs`, and `.mjs` files in the output\n * directory, rewriting imports in-place. Files whose content is unchanged\n * are not written back to disk.\n *\n * @param options - Configuration options for this bundle run\n */\n bundle(options: BundlerOptions): void {\n const rootDir = path.resolve(options.rootDir || process.cwd());\n const outDir = path.resolve(options.outDir);\n const resolvedPaths = this.loadConfig(rootDir, options.configPath);\n const compiledAliases = this.compileAliases(resolvedPaths);\n\n this._bundleDir(\n options.ext,\n outDir,\n rootDir,\n resolvedPaths,\n compiledAliases,\n outDir\n );\n }\n\n /**\n * Internal recursive directory walker, separated so that `bundle()` only\n * resolves config once at the top level rather than on every recursion.\n */\n private _bundleDir(\n ext: string,\n rootOutDir: string,\n rootDir: string,\n resolvedPaths: ResolvedPaths,\n compiledAliases: CompiledAlias[],\n dir: string\n ): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n this._bundleDir(\n ext,\n rootOutDir,\n rootDir,\n resolvedPaths,\n compiledAliases,\n fullPath\n );\n } else if (/\\.(js|cjs|mjs)$/.test(entry.name)) {\n const content = fs.readFileSync(fullPath, \"utf8\");\n const updated = this.rewriteImports(\n content,\n path.dirname(fullPath),\n rootOutDir,\n rootDir,\n ext,\n resolvedPaths,\n compiledAliases\n );\n if (updated !== content) fs.writeFileSync(fullPath, updated);\n }\n }\n }\n}\n\nexport const bundler = new Bundler();\n"]}
|