arkos 1.3.9-canary.2 → 1.3.9-canary.4
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/modules/auth/auth.service.js +4 -4
- package/dist/cjs/modules/auth/auth.service.js.map +1 -1
- package/dist/cjs/modules/error-handler/error-handler.controller.js +2 -2
- package/dist/cjs/modules/error-handler/error-handler.controller.js.map +1 -1
- package/dist/cjs/modules/file-upload/file-upload.service.js +3 -6
- package/dist/cjs/modules/file-upload/file-upload.service.js.map +1 -1
- package/dist/cjs/utils/cli/build.js +3 -2
- package/dist/cjs/utils/cli/build.js.map +1 -1
- package/dist/cjs/utils/cli/start.js +1 -0
- package/dist/cjs/utils/cli/start.js.map +1 -1
- package/dist/cjs/utils/cli/utils/cli.helpers.js +1 -1
- package/dist/cjs/utils/dotenv.helpers.js +2 -1
- package/dist/cjs/utils/dotenv.helpers.js.map +1 -1
- package/dist/esm/modules/auth/auth.service.js +4 -4
- package/dist/esm/modules/auth/auth.service.js.map +1 -1
- package/dist/esm/modules/error-handler/error-handler.controller.js +2 -2
- package/dist/esm/modules/error-handler/error-handler.controller.js.map +1 -1
- package/dist/esm/modules/file-upload/file-upload.service.js +3 -6
- package/dist/esm/modules/file-upload/file-upload.service.js.map +1 -1
- package/dist/esm/utils/cli/build.js +3 -2
- package/dist/esm/utils/cli/build.js.map +1 -1
- package/dist/esm/utils/cli/start.js +1 -0
- 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/dotenv.helpers.js +2 -1
- package/dist/esm/utils/dotenv.helpers.js.map +1 -1
- package/package.json +1 -1
|
@@ -32,10 +32,10 @@ class AuthService {
|
|
|
32
32
|
}
|
|
33
33
|
signJwtToken(id, expiresIn, secret) {
|
|
34
34
|
const { authentication: configs } = (0, server_1.getArkosConfig)();
|
|
35
|
-
if (process.env.
|
|
35
|
+
if (process.env.ARKOS_BUILD === "true" &&
|
|
36
36
|
!process.env.JWT_SECRET &&
|
|
37
37
|
!configs?.jwt?.secret)
|
|
38
|
-
throw new app_error_1.default("Missing JWT secret on production!", 500,
|
|
38
|
+
throw new app_error_1.default("Missing JWT secret on production!", 500, "MissingJWTOnProduction");
|
|
39
39
|
secret =
|
|
40
40
|
secret ||
|
|
41
41
|
configs?.jwt?.secret ||
|
|
@@ -99,10 +99,10 @@ class AuthService {
|
|
|
99
99
|
}
|
|
100
100
|
async verifyJwtToken(token, secret) {
|
|
101
101
|
const { authentication: configs } = (0, server_1.getArkosConfig)();
|
|
102
|
-
if (process.env.
|
|
102
|
+
if (process.env.ARKOS_BUILD === "true" &&
|
|
103
103
|
!process.env.JWT_SECRET &&
|
|
104
104
|
!configs?.jwt?.secret)
|
|
105
|
-
throw new app_error_1.default("Missing JWT secret
|
|
105
|
+
throw new app_error_1.default("Missing JWT secret in production", 500, "MissingJWTSecretInProduction");
|
|
106
106
|
secret =
|
|
107
107
|
secret ||
|
|
108
108
|
configs?.jwt?.secret ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../../../src/modules/auth/auth.service.ts"],"names":[],"mappings":"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","sourcesContent":["import jwt, { SignOptions } from \"jsonwebtoken\";\nimport bcrypt from \"bcryptjs\";\nimport { User } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { callNext } from \"../base/base.middlewares\";\nimport { getArkosConfig } from \"../../server\";\nimport arkosEnv from \"../../utils/arkos-env\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport {\n ArkosRequest,\n ArkosResponse,\n ArkosNextFunction,\n ArkosRequestHandler,\n} from \"../../types\";\nimport {\n AuthJwtPayload,\n AccessAction,\n AccessControlConfig,\n AuthenticationControlConfig,\n} from \"../../types/auth\";\nimport { MsDuration, toMs } from \"./utils/helpers/auth.controller.helpers\";\nimport { appModules, getModuleComponents } from \"../../utils/dynamic-loader\";\nimport { kebabCase } from \"../../exports/utils\";\nimport {\n invaliAuthTokenError,\n loginRequiredError,\n} from \"./utils/auth-error-objects\";\nimport authActionService from \"./utils/services/auth-action.service\";\nimport { CookieOptions } from \"express\";\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nexport class AuthService {\n /**\n * Object containing a combination of actions per resource, tracked by each set of calls of `authService.handleAccessControl`, this can be accessed through the `authService` object or through the endpoint\n */\n actionsPerResource: Record<string, Set<string>> = {};\n\n /**\n * Signs a JWT token for the user.\n *\n * @param {number | string} id - The unique identifier of the user to generate the token for.\n * @param {string | number} [expiresIn] - The expiration time for the token. Defaults to environment variable `JWT_EXPIRES_IN`.\n * @param {string} [secret] - The secret key used to sign the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {string} The signed JWT token.\n */\n signJwtToken(\n id: number | string,\n expiresIn?: MsDuration | number,\n secret?: string\n ): string {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.NODE_ENV === \"production\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret on production!\",\n 500,\n {},\n \"MissingJWTOnProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n expiresIn = (expiresIn ||\n configs?.jwt?.expiresIn ||\n process.env.JWT_EXPIRES_IN ||\n arkosEnv.JWT_EXPIRES_IN) as keyof SignOptions[\"expiresIn\"];\n\n return jwt.sign({ id }, secret, {\n expiresIn: expiresIn as MsDuration,\n });\n }\n\n /**\n * Retrieves cookie configuration options for JWT authentication.\n *\n * Merges configuration from multiple sources in order of precedence:\n * 1. Arkos configuration file\n * 2. Environment variables\n * 3. Request properties (for secure flag)\n * 4. Default fallback values\n *\n * @param req - ArkosRequest object used to determine if the connection is secure\n * @returns Cookie options object with expires, httpOnly, secure, and sameSite properties\n *\n * @example\n * ```typescript\n * const cookieOptions = authService.getJwtCookieOptions(req);\n * res.cookie('jwt', token, cookieOptions);\n * ```\n */\n getJwtCookieOptions(req: ArkosRequest) {\n const arkosConfig = getArkosConfig();\n const authConfigs = arkosConfig?.authentication;\n\n if (!req)\n throw new Error(\"Missing req object in order get jwt cookie options\");\n\n const sameSite =\n authConfigs?.jwt?.cookie?.sameSite ||\n (process.env.JWT_COOKIE_SAME_SITE as\n | \"none\"\n | \"lax\"\n | \"strict\"\n | undefined) ||\n \"lax\";\n\n return {\n expires: new Date(\n Date.now() +\n Number(\n toMs(\n authConfigs?.jwt?.expiresIn ||\n (process.env.JWT_EXPIRES_IN as MsDuration) ||\n (arkosEnv.JWT_EXPIRES_IN as MsDuration)\n )\n )\n ),\n httpOnly:\n authConfigs?.jwt?.cookie?.httpOnly ??\n (process.env.JWT_COOKIE_HTTP_ONLY !== undefined\n ? process.env.JWT_COOKIE_HTTP_ONLY === \"true\"\n : undefined) ??\n true,\n secure:\n authConfigs?.jwt?.cookie?.secure ??\n (process.env.JWT_COOKIE_SECURE === \"true\" ||\n req.secure ||\n req.headers[\"x-forwarded-proto\"] === \"https\" ||\n sameSite === \"none\"),\n sameSite,\n };\n }\n\n /**\n * Is used by default internally by Arkos under `BaseService` class to check if the password is already hashed.\n *\n * This was just added to prevent unwanted errors when someone just forgets that the `BaseService` class will automatically hash the password field using `authService.hashPassword` by default.\n *\n * So now before `BaseService` hashes it will test it.\n *\n *\n * @param password The password to be tested if is hashed\n * @returns\n */\n isPasswordHashed(password: string) {\n return !Number.isNaN(bcrypt.getRounds(password) * 1);\n }\n\n /**\n * Compares a candidate password with the stored user password to check if they match.\n *\n * @param {string} candidatePassword - The password provided by the user during login.\n * @param {string} userPassword - The password stored in the database.\n * @returns {Promise<boolean>} Returns true if the passwords match, otherwise false.\n */\n async isCorrectPassword(\n candidatePassword: string,\n userPassword: string\n ): Promise<boolean> {\n return await bcrypt.compare(candidatePassword, userPassword);\n }\n\n /**\n * Hashes a plain text password using bcrypt.\n *\n * @param {string} password - The password to be hashed.\n * @returns {Promise<string>} Returns the hashed password.\n */\n async hashPassword(password: string): Promise<string> {\n return await bcrypt.hash(password, 12);\n }\n\n /**\n * Checks if a password is strong, requiring uppercase, lowercase, and numeric characters as the default.\n *\n * **NB**: You must pay attention when using custom validation with zod or class-validator, try to use the same regex always.\n *\n * **Note**: You can define it when calling arkos.init()\n * ```ts\n * arkos.init({\n * authentication: {\n * passwordValidation:{ regex: /your-desired-regex/, message: 'password must contain...'}\n * }\n * })\n * ```\n *\n * @param {string} password - The password to check.\n * @returns {boolean} Returns true if the password meets the strength criteria, otherwise false.\n */\n public isPasswordStrong(password: string): boolean {\n const initAuthConfigs = getArkosConfig()?.authentication;\n\n const strongPasswordRegex =\n initAuthConfigs?.passwordValidation?.regex ||\n /^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).+$/;\n return strongPasswordRegex.test(password);\n }\n\n /**\n * Checks if a user has changed their password after the JWT was issued.\n *\n * @param {User} user - The user object containing the passwordChangedAt field.\n * @param {number} JWTTimestamp - The timestamp when the JWT was issued.\n * @returns {boolean} Returns true if the user changed their password after the JWT was issued, otherwise false.\n */\n userChangedPasswordAfter(user: User, JWTTimestamp: number): boolean {\n if (user.passwordChangedAt) {\n const convertedTimestamp = parseInt(\n String(user.passwordChangedAt.getTime() / 1000),\n 10\n );\n\n return JWTTimestamp < convertedTimestamp;\n }\n return false;\n }\n\n /**\n * Verifies the authenticity of a JWT token.\n *\n * @param {string} token - The JWT token to verify.\n * @param {string} [secret] - The secret key used to verify the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {Promise<AuthJwtPayload>} Returns the decoded JWT payload if the token is valid.\n * @throws {Error} Throws an error if the token is invalid or expired.\n */\n async verifyJwtToken(\n token: string,\n secret?: string\n ): Promise<AuthJwtPayload> {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.NODE_ENV === \"production\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\"Missing JWT secret!\", 500);\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n return new Promise((resolve, reject) => {\n jwt.verify(token, secret, (err, decoded) => {\n if (err) reject(err);\n else resolve(decoded as AuthJwtPayload);\n });\n });\n }\n\n /**\n * Checks if a user has permission for a specific action using static access control rules.\n * Validates user roles against predefined access control configuration.\n *\n * @param user - The user object containing role or roles field\n * @param action - The action being performed\n * @param accessControl - Access control configuration (array of roles or object with action-role mappings)\n * @returns True if user has permission, false otherwise\n * @throws Error if user doesn't have role/roles field\n */\n protected checkStaticAccessControl(\n user: User,\n action: string,\n accessControl: AccessControlConfig\n ) {\n if (!user?.role && !user.roles)\n throw Error(\n \"Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.\"\n );\n\n let authorizedRoles: string[] = [];\n\n if (Array.isArray(accessControl)) authorizedRoles = accessControl;\n else if (accessControl[action])\n authorizedRoles = Array.isArray(accessControl[action])\n ? accessControl[action]\n : accessControl[action].roles;\n\n const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];\n\n return !!userRoles.some((role: string) => authorizedRoles.includes(role));\n }\n\n /**\n * Checks if a user has permission for a specific action and resource using dynamic access control.\n * Queries the database to verify user's role permissions.\n *\n * @param userId - The unique identifier of the user\n * @param action - The action being performed\n * @param resource - The resource being accessed\n * @returns Promise resolving to true if user has permission, false otherwise\n */\n protected async checkDynamicAccessControl(\n userId: string,\n action: string,\n resource: string\n ) {\n const prisma = getPrismaInstance();\n return !!(await prisma.userRole.findFirst({\n where: {\n userId,\n role: {\n permissions: {\n some: {\n resource,\n action,\n },\n },\n },\n },\n select: { id: true },\n }));\n }\n\n /**\n * Middleware function to handle access control based on user roles and permissions.\n *\n * @param {AccessAction} action - The action being performed (e.g., create, update, delete, view).\n * @param {string} resource - The resource name that the action is being performed on (e.g., \"User\", \"Post\").\n * @param {AccessControlConfig} accessControl - The access control configuration.\n * @returns {ArkosRequestHandler} The middleware function that checks if the user has permission to perform the action.\n */\n handleAccessControl(\n action: AccessAction,\n resource: string,\n accessControl?: AccessControlConfig\n ): ArkosRequestHandler {\n if (\n !accessControl &&\n appModules.some(\n (appModule) => kebabCase(appModule) === kebabCase(resource)\n )\n )\n accessControl = getModuleComponents(resource)?.authConfigs?.accessControl;\n\n authActionService.add(action, resource, accessControl);\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n if (req.user) {\n const user = req.user as User;\n const configs = getArkosConfig();\n\n if (user.isSuperUser) {\n next();\n return;\n }\n\n const notEnoughPermissionsError = new AppError(\n \"You do not have permission to perfom this action\",\n 403,\n {},\n \"NotEnoughPermissions\"\n );\n\n if (configs?.authentication?.mode === \"dynamic\") {\n const hasPermission = await this.checkDynamicAccessControl(\n user.id,\n action,\n resource\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n } else if (configs?.authentication?.mode === \"static\") {\n if (!accessControl) return next(notEnoughPermissionsError);\n\n const hasPermission = this.checkStaticAccessControl(\n user,\n action,\n accessControl\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n }\n }\n\n next();\n }\n );\n }\n\n /**\n * Processes the cookies or authoriation token and returns the user.\n * @param req\n * @returns {Promise<User | null>} - if authentication is turned off in arkosConfig it returns null\n * @throws {AppError} Throws an error if the token is invalid or the user is not logged in.\n */\n async getAuthenticatedUser(req: ArkosRequest): Promise<User | null> {\n const arkosConfig = getArkosConfig();\n if (!arkosConfig?.authentication) return null;\n\n const prisma = getPrismaInstance();\n\n let token: string | undefined;\n\n if (\n req?.headers?.authorization &&\n req?.headers?.authorization.startsWith(\"Bearer\")\n ) {\n token = req?.headers?.authorization.split(\" \")[1];\n } else if (req?.cookies?.arkos_access_token !== \"no-token\" && req.cookies) {\n token = req?.cookies?.arkos_access_token;\n }\n\n if (!token) throw loginRequiredError;\n\n let decoded: AuthJwtPayload | undefined;\n\n try {\n decoded = await this.verifyJwtToken(token);\n } catch (err) {\n throw invaliAuthTokenError;\n }\n\n if (!decoded?.id) throw invaliAuthTokenError;\n const user: any | null = await (prisma as any).user.findUnique({\n where: { id: String(decoded.id) },\n });\n\n if (!user)\n throw new AppError(\n \"The user belonging to this token does no longer exists\",\n 401,\n {},\n \"UserNoLongerExists\"\n );\n\n if (\n this.userChangedPasswordAfter(user, decoded.iat!) &&\n !req.path?.includes?.(\"logout\")\n )\n throw new AppError(\n \"User recently changed password! Please log in again.\",\n 401,\n {},\n \"PasswordChanged\"\n );\n\n req.accessToken = token;\n return user;\n }\n\n /**\n * Middleware function to authenticate the user based on the JWT token.\n *\n * @param {ArkosRequest} req - The request object.\n * @param {ArkosResponse} res - The response object.\n * @param {ArkosNextFunction} next - The next middleware function to be called.\n * @returns {void}\n */\n authenticate = catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n const arkosConfig = getArkosConfig();\n if (!arkosConfig?.authentication) {\n next();\n return;\n }\n\n req.user = (await this.getAuthenticatedUser(req)) as User;\n next();\n }\n );\n\n /**\n * Handles authentication control by checking the `authenticationControl` configuration in the `authConfigs`.\n *\n * @param {ControllerActions} action - The action being performed (e.g., create, update, delete, view).\n * @param {AuthenticationControlConfig} authenticationControl - The authentication configuration object.\n * @returns {ArkosRequestHandler} The middleware function that checks if authentication is required.\n */\n handleAuthenticationControl(\n action: AccessAction,\n authenticationControl?: AuthenticationControlConfig | undefined\n ): ArkosRequestHandler {\n if (authenticationControl && typeof authenticationControl === \"object\") {\n if (authenticationControl[action] === false) return callNext;\n else if (authenticationControl[action] === true) return this.authenticate;\n } else return this.authenticate;\n\n return this.authenticate;\n }\n\n /**\n * Creates a permission checker function for a specific action and resource.\n *\n * PS: This method should be called during application initialization to build permission validators.\n *\n * @see {@link https://www.arkosjs.com/docs/advanced-guide/fine-grained-access-control}\n *\n * @param action - The action to check permission for (e.g., 'View', 'Create', 'Delete')\n * @param resource - The resource being accessed, must be in kebabCase (e.g., 'user', 'cart-item', 'order')\n * @param accessControl - Access control rules (required for static authentication mode), and it is automatically loaded for known modules such as all prisma models, auth and file-upload.\n * @returns A function that takes a user object and returns a boolean indicating permission status\n *\n * @example\n * ```typescript\n * const hasViewProductPermission = await authService.permission('View', 'product');\n *\n * // Later in handler:\n * const canAccess = await hasViewProductPermission(user);\n * if (canAccess) {\n * // User has permission\n * }\n * ```\n */\n permission(\n action: string,\n resource: string,\n accessControl?: AccessControlConfig\n ) {\n // Check if called during request handling (deep call stack indicates handler execution)\n const stack = new Error().stack;\n\n if (stack?.includes(\"node_modules/express/lib/router/index.js\"))\n throw new Error(\n \"authService.permission() should be called during application initialization level.\"\n );\n\n authActionService.add(action, resource, accessControl);\n\n return async (user: Record<string, any>): Promise<boolean> => {\n // getArkosConfig must not be called the same time as arkos.init()\n const configs = getArkosConfig();\n if (!configs?.authentication)\n throw Error(\n \"Validation Error: Trying to use authService.permission without setting up authentication.\"\n );\n\n if (!user) throw loginRequiredError;\n if (user.isSuperUser) return true;\n\n if (configs?.authentication?.mode === \"dynamic\") {\n return await this.checkDynamicAccessControl(user?.id, action, resource);\n } else if (configs?.authentication?.mode === \"static\") {\n if (!accessControl && appModules.includes(kebabCase(resource)))\n accessControl = getModuleComponents(kebabCase(resource))?.authConfigs\n ?.accessControl;\n\n return (\n !!accessControl &&\n this.checkStaticAccessControl(user as any, action, accessControl)\n );\n }\n return false;\n };\n }\n}\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nconst authService = new AuthService();\n\nexport default authService;\n"]}
|
|
1
|
+
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../../../src/modules/auth/auth.service.ts"],"names":[],"mappings":"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","sourcesContent":["import jwt, { SignOptions } from \"jsonwebtoken\";\nimport bcrypt from \"bcryptjs\";\nimport { User } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { callNext } from \"../base/base.middlewares\";\nimport { getArkosConfig } from \"../../server\";\nimport arkosEnv from \"../../utils/arkos-env\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport {\n ArkosRequest,\n ArkosResponse,\n ArkosNextFunction,\n ArkosRequestHandler,\n} from \"../../types\";\nimport {\n AuthJwtPayload,\n AccessAction,\n AccessControlConfig,\n AuthenticationControlConfig,\n} from \"../../types/auth\";\nimport { MsDuration, toMs } from \"./utils/helpers/auth.controller.helpers\";\nimport { appModules, getModuleComponents } from \"../../utils/dynamic-loader\";\nimport { kebabCase } from \"../../exports/utils\";\nimport {\n invaliAuthTokenError,\n loginRequiredError,\n} from \"./utils/auth-error-objects\";\nimport authActionService from \"./utils/services/auth-action.service\";\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nexport class AuthService {\n /**\n * Object containing a combination of actions per resource, tracked by each set of calls of `authService.handleAccessControl`, this can be accessed through the `authService` object or through the endpoint\n */\n actionsPerResource: Record<string, Set<string>> = {};\n\n /**\n * Signs a JWT token for the user.\n *\n * @param {number | string} id - The unique identifier of the user to generate the token for.\n * @param {string | number} [expiresIn] - The expiration time for the token. Defaults to environment variable `JWT_EXPIRES_IN`.\n * @param {string} [secret] - The secret key used to sign the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {string} The signed JWT token.\n */\n signJwtToken(\n id: number | string,\n expiresIn?: MsDuration | number,\n secret?: string\n ): string {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.ARKOS_BUILD === \"true\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret on production!\",\n 500,\n \"MissingJWTOnProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n expiresIn = (expiresIn ||\n configs?.jwt?.expiresIn ||\n process.env.JWT_EXPIRES_IN ||\n arkosEnv.JWT_EXPIRES_IN) as keyof SignOptions[\"expiresIn\"];\n\n return jwt.sign({ id }, secret, {\n expiresIn: expiresIn as MsDuration,\n });\n }\n\n /**\n * Retrieves cookie configuration options for JWT authentication.\n *\n * Merges configuration from multiple sources in order of precedence:\n * 1. Arkos configuration file\n * 2. Environment variables\n * 3. Request properties (for secure flag)\n * 4. Default fallback values\n *\n * @param req - ArkosRequest object used to determine if the connection is secure\n * @returns Cookie options object with expires, httpOnly, secure, and sameSite properties\n *\n * @example\n * ```typescript\n * const cookieOptions = authService.getJwtCookieOptions(req);\n * res.cookie('jwt', token, cookieOptions);\n * ```\n */\n getJwtCookieOptions(req: ArkosRequest) {\n const arkosConfig = getArkosConfig();\n const authConfigs = arkosConfig?.authentication;\n\n if (!req)\n throw new Error(\"Missing req object in order get jwt cookie options\");\n\n const sameSite =\n authConfigs?.jwt?.cookie?.sameSite ||\n (process.env.JWT_COOKIE_SAME_SITE as\n | \"none\"\n | \"lax\"\n | \"strict\"\n | undefined) ||\n \"lax\";\n\n return {\n expires: new Date(\n Date.now() +\n Number(\n toMs(\n authConfigs?.jwt?.expiresIn ||\n (process.env.JWT_EXPIRES_IN as MsDuration) ||\n (arkosEnv.JWT_EXPIRES_IN as MsDuration)\n )\n )\n ),\n httpOnly:\n authConfigs?.jwt?.cookie?.httpOnly ??\n (process.env.JWT_COOKIE_HTTP_ONLY !== undefined\n ? process.env.JWT_COOKIE_HTTP_ONLY === \"true\"\n : undefined) ??\n true,\n secure:\n authConfigs?.jwt?.cookie?.secure ??\n (process.env.JWT_COOKIE_SECURE === \"true\" ||\n req.secure ||\n req.headers[\"x-forwarded-proto\"] === \"https\" ||\n sameSite === \"none\"),\n sameSite,\n };\n }\n\n /**\n * Is used by default internally by Arkos under `BaseService` class to check if the password is already hashed.\n *\n * This was just added to prevent unwanted errors when someone just forgets that the `BaseService` class will automatically hash the password field using `authService.hashPassword` by default.\n *\n * So now before `BaseService` hashes it will test it.\n *\n *\n * @param password The password to be tested if is hashed\n * @returns\n */\n isPasswordHashed(password: string) {\n return !Number.isNaN(bcrypt.getRounds(password) * 1);\n }\n\n /**\n * Compares a candidate password with the stored user password to check if they match.\n *\n * @param {string} candidatePassword - The password provided by the user during login.\n * @param {string} userPassword - The password stored in the database.\n * @returns {Promise<boolean>} Returns true if the passwords match, otherwise false.\n */\n async isCorrectPassword(\n candidatePassword: string,\n userPassword: string\n ): Promise<boolean> {\n return await bcrypt.compare(candidatePassword, userPassword);\n }\n\n /**\n * Hashes a plain text password using bcrypt.\n *\n * @param {string} password - The password to be hashed.\n * @returns {Promise<string>} Returns the hashed password.\n */\n async hashPassword(password: string): Promise<string> {\n return await bcrypt.hash(password, 12);\n }\n\n /**\n * Checks if a password is strong, requiring uppercase, lowercase, and numeric characters as the default.\n *\n * **NB**: You must pay attention when using custom validation with zod or class-validator, try to use the same regex always.\n *\n * **Note**: You can define it when calling arkos.init()\n * ```ts\n * arkos.init({\n * authentication: {\n * passwordValidation:{ regex: /your-desired-regex/, message: 'password must contain...'}\n * }\n * })\n * ```\n *\n * @param {string} password - The password to check.\n * @returns {boolean} Returns true if the password meets the strength criteria, otherwise false.\n */\n public isPasswordStrong(password: string): boolean {\n const initAuthConfigs = getArkosConfig()?.authentication;\n\n const strongPasswordRegex =\n initAuthConfigs?.passwordValidation?.regex ||\n /^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).+$/;\n return strongPasswordRegex.test(password);\n }\n\n /**\n * Checks if a user has changed their password after the JWT was issued.\n *\n * @param {User} user - The user object containing the passwordChangedAt field.\n * @param {number} JWTTimestamp - The timestamp when the JWT was issued.\n * @returns {boolean} Returns true if the user changed their password after the JWT was issued, otherwise false.\n */\n userChangedPasswordAfter(user: User, JWTTimestamp: number): boolean {\n if (user.passwordChangedAt) {\n const convertedTimestamp = parseInt(\n String(user.passwordChangedAt.getTime() / 1000),\n 10\n );\n\n return JWTTimestamp < convertedTimestamp;\n }\n return false;\n }\n\n /**\n * Verifies the authenticity of a JWT token.\n *\n * @param {string} token - The JWT token to verify.\n * @param {string} [secret] - The secret key used to verify the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {Promise<AuthJwtPayload>} Returns the decoded JWT payload if the token is valid.\n * @throws {Error} Throws an error if the token is invalid or expired.\n */\n async verifyJwtToken(\n token: string,\n secret?: string\n ): Promise<AuthJwtPayload> {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.ARKOS_BUILD === \"true\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret in production\",\n 500,\n \"MissingJWTSecretInProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n return new Promise((resolve, reject) => {\n jwt.verify(token, secret, (err, decoded) => {\n if (err) reject(err);\n else resolve(decoded as AuthJwtPayload);\n });\n });\n }\n\n /**\n * Checks if a user has permission for a specific action using static access control rules.\n * Validates user roles against predefined access control configuration.\n *\n * @param user - The user object containing role or roles field\n * @param action - The action being performed\n * @param accessControl - Access control configuration (array of roles or object with action-role mappings)\n * @returns True if user has permission, false otherwise\n * @throws Error if user doesn't have role/roles field\n */\n protected checkStaticAccessControl(\n user: User,\n action: string,\n accessControl: AccessControlConfig\n ) {\n if (!user?.role && !user.roles)\n throw Error(\n \"Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.\"\n );\n\n let authorizedRoles: string[] = [];\n\n if (Array.isArray(accessControl)) authorizedRoles = accessControl;\n else if (accessControl[action])\n authorizedRoles = Array.isArray(accessControl[action])\n ? accessControl[action]\n : accessControl[action].roles;\n\n const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];\n\n return !!userRoles.some((role: string) => authorizedRoles.includes(role));\n }\n\n /**\n * Checks if a user has permission for a specific action and resource using dynamic access control.\n * Queries the database to verify user's role permissions.\n *\n * @param userId - The unique identifier of the user\n * @param action - The action being performed\n * @param resource - The resource being accessed\n * @returns Promise resolving to true if user has permission, false otherwise\n */\n protected async checkDynamicAccessControl(\n userId: string,\n action: string,\n resource: string\n ) {\n const prisma = getPrismaInstance();\n return !!(await prisma.userRole.findFirst({\n where: {\n userId,\n role: {\n permissions: {\n some: {\n resource,\n action,\n },\n },\n },\n },\n select: { id: true },\n }));\n }\n\n /**\n * Middleware function to handle access control based on user roles and permissions.\n *\n * @param {AccessAction} action - The action being performed (e.g., create, update, delete, view).\n * @param {string} resource - The resource name that the action is being performed on (e.g., \"User\", \"Post\").\n * @param {AccessControlConfig} accessControl - The access control configuration.\n * @returns {ArkosRequestHandler} The middleware function that checks if the user has permission to perform the action.\n */\n handleAccessControl(\n action: AccessAction,\n resource: string,\n accessControl?: AccessControlConfig\n ): ArkosRequestHandler {\n if (\n !accessControl &&\n appModules.some(\n (appModule) => kebabCase(appModule) === kebabCase(resource)\n )\n )\n accessControl = getModuleComponents(resource)?.authConfigs?.accessControl;\n\n authActionService.add(action, resource, accessControl);\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n if (req.user) {\n const user = req.user as User;\n const configs = getArkosConfig();\n\n if (user.isSuperUser) {\n next();\n return;\n }\n\n const notEnoughPermissionsError = new AppError(\n \"You do not have permission to perfom this action\",\n 403,\n {},\n \"NotEnoughPermissions\"\n );\n\n if (configs?.authentication?.mode === \"dynamic\") {\n const hasPermission = await this.checkDynamicAccessControl(\n user.id,\n action,\n resource\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n } else if (configs?.authentication?.mode === \"static\") {\n if (!accessControl) return next(notEnoughPermissionsError);\n\n const hasPermission = this.checkStaticAccessControl(\n user,\n action,\n accessControl\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n }\n }\n\n next();\n }\n );\n }\n\n /**\n * Processes the cookies or authoriation token and returns the user.\n * @param req\n * @returns {Promise<User | null>} - if authentication is turned off in arkosConfig it returns null\n * @throws {AppError} Throws an error if the token is invalid or the user is not logged in.\n */\n async getAuthenticatedUser(req: ArkosRequest): Promise<User | null> {\n const arkosConfig = getArkosConfig();\n if (!arkosConfig?.authentication) return null;\n\n const prisma = getPrismaInstance();\n\n let token: string | undefined;\n\n if (\n req?.headers?.authorization &&\n req?.headers?.authorization.startsWith(\"Bearer\")\n ) {\n token = req?.headers?.authorization.split(\" \")[1];\n } else if (req?.cookies?.arkos_access_token !== \"no-token\" && req.cookies) {\n token = req?.cookies?.arkos_access_token;\n }\n\n if (!token) throw loginRequiredError;\n\n let decoded: AuthJwtPayload | undefined;\n\n try {\n decoded = await this.verifyJwtToken(token);\n } catch (err) {\n throw invaliAuthTokenError;\n }\n\n if (!decoded?.id) throw invaliAuthTokenError;\n const user: any | null = await (prisma as any).user.findUnique({\n where: { id: String(decoded.id) },\n });\n\n if (!user)\n throw new AppError(\n \"The user belonging to this token does no longer exists\",\n 401,\n {},\n \"UserNoLongerExists\"\n );\n\n if (\n this.userChangedPasswordAfter(user, decoded.iat!) &&\n !req.path?.includes?.(\"logout\")\n )\n throw new AppError(\n \"User recently changed password! Please log in again.\",\n 401,\n {},\n \"PasswordChanged\"\n );\n\n req.accessToken = token;\n return user;\n }\n\n /**\n * Middleware function to authenticate the user based on the JWT token.\n *\n * @param {ArkosRequest} req - The request object.\n * @param {ArkosResponse} res - The response object.\n * @param {ArkosNextFunction} next - The next middleware function to be called.\n * @returns {void}\n */\n authenticate = catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n const arkosConfig = getArkosConfig();\n if (!arkosConfig?.authentication) {\n next();\n return;\n }\n\n req.user = (await this.getAuthenticatedUser(req)) as User;\n next();\n }\n );\n\n /**\n * Handles authentication control by checking the `authenticationControl` configuration in the `authConfigs`.\n *\n * @param {ControllerActions} action - The action being performed (e.g., create, update, delete, view).\n * @param {AuthenticationControlConfig} authenticationControl - The authentication configuration object.\n * @returns {ArkosRequestHandler} The middleware function that checks if authentication is required.\n */\n handleAuthenticationControl(\n action: AccessAction,\n authenticationControl?: AuthenticationControlConfig | undefined\n ): ArkosRequestHandler {\n if (authenticationControl && typeof authenticationControl === \"object\") {\n if (authenticationControl[action] === false) return callNext;\n else if (authenticationControl[action] === true) return this.authenticate;\n } else return this.authenticate;\n\n return this.authenticate;\n }\n\n /**\n * Creates a permission checker function for a specific action and resource.\n *\n * PS: This method should be called during application initialization to build permission validators.\n *\n * @see {@link https://www.arkosjs.com/docs/advanced-guide/fine-grained-access-control}\n *\n * @param action - The action to check permission for (e.g., 'View', 'Create', 'Delete')\n * @param resource - The resource being accessed, must be in kebabCase (e.g., 'user', 'cart-item', 'order')\n * @param accessControl - Access control rules (required for static authentication mode), and it is automatically loaded for known modules such as all prisma models, auth and file-upload.\n * @returns A function that takes a user object and returns a boolean indicating permission status\n *\n * @example\n * ```typescript\n * const hasViewProductPermission = await authService.permission('View', 'product');\n *\n * // Later in handler:\n * const canAccess = await hasViewProductPermission(user);\n * if (canAccess) {\n * // User has permission\n * }\n * ```\n */\n permission(\n action: string,\n resource: string,\n accessControl?: AccessControlConfig\n ) {\n // Check if called during request handling (deep call stack indicates handler execution)\n const stack = new Error().stack;\n\n if (stack?.includes(\"node_modules/express/lib/router/index.js\"))\n throw new Error(\n \"authService.permission() should be called during application initialization level.\"\n );\n\n authActionService.add(action, resource, accessControl);\n\n return async (user: Record<string, any>): Promise<boolean> => {\n // getArkosConfig must not be called the same time as arkos.init()\n const configs = getArkosConfig();\n if (!configs?.authentication)\n throw Error(\n \"Validation Error: Trying to use authService.permission without setting up authentication.\"\n );\n\n if (!user) throw loginRequiredError;\n if (user.isSuperUser) return true;\n\n if (configs?.authentication?.mode === \"dynamic\") {\n return await this.checkDynamicAccessControl(user?.id, action, resource);\n } else if (configs?.authentication?.mode === \"static\") {\n if (!accessControl && appModules.includes(kebabCase(resource)))\n accessControl = getModuleComponents(kebabCase(resource))?.authConfigs\n ?.accessControl;\n\n return (\n !!accessControl &&\n this.checkStaticAccessControl(user as any, action, accessControl)\n );\n }\n return false;\n };\n }\n}\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nconst authService = new AuthService();\n\nexport default authService;\n"]}
|
|
@@ -45,7 +45,7 @@ function errorHandler(err, req, res, _) {
|
|
|
45
45
|
message: err.message,
|
|
46
46
|
stack: err?.stack || undefined,
|
|
47
47
|
};
|
|
48
|
-
if (process.env.
|
|
48
|
+
if (process.env.ARKOS_BUILD === "true")
|
|
49
49
|
delete error?.stack;
|
|
50
50
|
if (err.name === "JsonWebTokenError")
|
|
51
51
|
error = errorControllerHelper.handleJWTError();
|
|
@@ -85,7 +85,7 @@ function errorHandler(err, req, res, _) {
|
|
|
85
85
|
error = errorControllerHelper.handleVersionMismatchError(err);
|
|
86
86
|
if (err.name === "NetworkError")
|
|
87
87
|
error = errorControllerHelper.handleNetworkError(err);
|
|
88
|
-
if (process.env.
|
|
88
|
+
if (process.env.ARKOS_BUILD !== "true")
|
|
89
89
|
return sendDevelopmentError({
|
|
90
90
|
...error,
|
|
91
91
|
message: error.message,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.controller.js","sourceRoot":"","sources":["../../../../src/modules/error-handler/error-handler.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { NextFunction, Request, Response } from \"express\";\nimport AppError from \"./utils/app-error\";\nimport * as errorControllerHelper from \"./utils/error-handler.helpers\";\nimport { server } from \"../../server\";\n\n/**\n * Error handling middleware for Express.\n *\n * This middleware function handles all errors in the Express application.\n * It checks for the environment (development or production) and sends appropriate error responses\n * based on whether the environment is production or not. It also maps specific errors such as\n * JWT errors, Prisma client errors, and database-related errors to specific helper functions for handling.\n *\n * @param {AppError} err - The error object thrown by the application.\n * @param {Request} req - The Express request object.\n * @param {Response} res - The Express response object.\n * @param {NextFunction} _ - The next middleware function in the chain.\n *\n * @returns {void} - Sends the response with the error details to the client.\n */\nexport default function errorHandler(\n err: AppError,\n req: Request,\n res: Response,\n _: NextFunction\n): void {\n console.error(\"[\\x1b[31mError\\x1b[0m]:\", err);\n\n err.statusCode = err.statusCode || 500;\n err.status = err.status || \"error\";\n\n let error: any = {\n ...err,\n message: err.message,\n stack: err?.stack || undefined,\n };\n\n if (process.env.NODE_ENV == \"production\") delete error?.stack;\n\n if (err.name === \"JsonWebTokenError\")\n error = errorControllerHelper.handleJWTError();\n if (err.name === \"TokenExpiredError\")\n error = errorControllerHelper.handleJWTExpired();\n\n if (err.name === \"PrismaClientValidationError\")\n error = errorControllerHelper.handlePrismaClientValidationError(err);\n if (err.name === \"PrismaClientInitializationError\")\n error = errorControllerHelper.handlePrismaClientInitializationError(err);\n if (err.code === \"P1000\")\n error = errorControllerHelper.handleAuthenticationError(err);\n if (err.code === \"P1001\")\n error = errorControllerHelper.handleServerNotReachableError(err);\n if (err.code === \"P1002\")\n error = errorControllerHelper.handleConnectionTimeoutError(err);\n if (err.code === \"P1003\")\n error = errorControllerHelper.handleDatabaseNotFoundError(err);\n if (err.code === \"P2000\")\n error = errorControllerHelper.handleFieldValueTooLargeError(err);\n if (err.code === \"P2001\")\n error = errorControllerHelper.handleRecordNotFoundError(err);\n if (err.code === \"P2002\")\n error = errorControllerHelper.handleUniqueConstraintError(err);\n if (err.code === \"P2003\")\n error = errorControllerHelper.handleForeignKeyConstraintError(err);\n if (err.code === \"P2004\")\n error = errorControllerHelper.handleConstraintFailedError(err);\n if (err.code === \"P2025\")\n error = errorControllerHelper.handleNonExistingRecord(err);\n if (err.code === \"P3000\")\n error = errorControllerHelper.handleSchemaCreationFailedError(err);\n if (err.code === \"P3001\")\n error = errorControllerHelper.handleMigrationAlreadyAppliedError(err);\n if (err.code === \"P3002\")\n error = errorControllerHelper.handleMigrationScriptFailedError(err);\n if (err.code === \"P3003\")\n error = errorControllerHelper.handleVersionMismatchError(err);\n\n if (err.name === \"NetworkError\")\n error = errorControllerHelper.handleNetworkError(err);\n\n if (process.env.NODE_ENV !== \"production\")\n return sendDevelopmentError(\n {\n ...error,\n message: error.message,\n stack: err.stack,\n originalError: err,\n },\n req,\n res\n );\n\n sendProductionError(error, req, res);\n}\n\n/**\n * Sends a detailed error response in development mode.\n *\n * In development, the error response includes full error details, including\n * the stack trace and the complete error message.\n *\n * @param {AppError} err - The error object.\n * @param {Request} req - The Express request object.\n * @param {Response} res - The Express response object.\n *\n * @returns {void} - Sends the response with the error details to the client.\n */\nfunction sendDevelopmentError(err: any, req: Request, res: Response): void {\n if (req.originalUrl.startsWith(\"/api\"))\n res.status(err.statusCode).json({\n ...err,\n message: err.message.split(\"\\n\")[err.message.split(\"\\n\").length - 1],\n stack: err.stack?.split(\"\\n\"),\n });\n else\n res.status(err.statusCode).json({\n title: \"Internal server error\",\n message: err.message,\n });\n}\n\n/**\n * Sends a generic error response in production mode.\n *\n * In production, sensitive error details (such as stack traces) are not exposed\n * to the client. Only operational errors are shown with a generic message.\n *\n * @param {AppError} err - The error object.\n * @param {Request} req - The Express request object.\n * @param {Response} res - The Express response object.\n *\n * @returns {void} - Sends the response with the error details to the client.\n */\nfunction sendProductionError(err: AppError, req: Request, res: Response): void {\n if (req.originalUrl.startsWith(\"/api\")) {\n if (err.isOperational)\n res.status(err.statusCode).json({\n status: err.status,\n message: err.message,\n meta: err.meta || {},\n code: err.code || \"Unknown\",\n });\n else\n res.status(500).json({\n status: \"error\",\n message: \"Internal server error, please try again later.\",\n code: \"Unknown\",\n meta: {},\n });\n\n return;\n }\n\n if (err.isOperational) {\n res.status(err.statusCode).json({\n title: \"Internal server error\",\n message: err.message,\n code: \"Unknown\",\n });\n return;\n }\n\n res.status(err.statusCode).json({\n title: \"Internal server error\",\n message: \"Internal server error, please try again later.\",\n });\n}\n\n/**\n * Gracefully handles process termination by listening for SIGTERM signal.\n *\n * - In production and staging environments, it will log a shutdown message\n * and attempt to close the server gracefully.\n * - In development or non-production environments, it will immediately exit the process.\n *\n * @returns {void}\n */\nprocess.on(\"SIGTERM\", () => {\n if (process.env.ARKOS_BUILD !== \"true\") {\n process.exit();\n } else {\n console.error(\"SIGTERM RECEIVED in Production. Shutting down gracefully!\");\n\n server.close(() => {\n console.error(\"Process terminated!!!\");\n process.exit();\n });\n }\n});\n"]}
|
|
1
|
+
{"version":3,"file":"error-handler.controller.js","sourceRoot":"","sources":["../../../../src/modules/error-handler/error-handler.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,+BAyEC;AA3FD,qFAAuE;AACvE,yCAAsC;AAiBtC,SAAwB,YAAY,CAClC,GAAa,EACb,GAAY,EACZ,GAAa,EACb,CAAe;IAEf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;IAE9C,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC;IACvC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC;IAEnC,IAAI,KAAK,GAAQ;QACf,GAAG,GAAG;QACN,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,SAAS;KAC/B,CAAC;IAEF,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM;QAAE,OAAO,KAAK,EAAE,KAAK,CAAC;IAE5D,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB;QAClC,KAAK,GAAG,qBAAqB,CAAC,cAAc,EAAE,CAAC;IACjD,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB;QAClC,KAAK,GAAG,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;IAEnD,IAAI,GAAG,CAAC,IAAI,KAAK,6BAA6B;QAC5C,KAAK,GAAG,qBAAqB,CAAC,iCAAiC,CAAC,GAAG,CAAC,CAAC;IACvE,IAAI,GAAG,CAAC,IAAI,KAAK,iCAAiC;QAChD,KAAK,GAAG,qBAAqB,CAAC,qCAAqC,CAAC,GAAG,CAAC,CAAC;IAC3E,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;IAC/D,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,6BAA6B,CAAC,GAAG,CAAC,CAAC;IACnE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC;IAClE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,6BAA6B,CAAC,GAAG,CAAC,CAAC;IACnE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;IAC/D,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,+BAA+B,CAAC,GAAG,CAAC,CAAC;IACrE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,+BAA+B,CAAC,GAAG,CAAC,CAAC;IACrE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,kCAAkC,CAAC,GAAG,CAAC,CAAC;IACxE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,gCAAgC,CAAC,GAAG,CAAC,CAAC;IACtE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,GAAG,qBAAqB,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC;IAEhE,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;QAC7B,KAAK,GAAG,qBAAqB,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAExD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM;QACpC,OAAO,oBAAoB,CACzB;YACE,GAAG,KAAK;YACR,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,aAAa,EAAE,GAAG;SACnB,EACD,GAAG,EACH,GAAG,CACJ,CAAC;IAEJ,mBAAmB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC;AAcD,SAAS,oBAAoB,CAAC,GAAQ,EAAE,GAAY,EAAE,GAAa;IACjE,IAAI,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC;QACpC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAC9B,GAAG,GAAG;YACN,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YACpE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC;SAC9B,CAAC,CAAC;;QAEH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAC9B,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC;AACP,CAAC;AAcD,SAAS,mBAAmB,CAAC,GAAa,EAAE,GAAY,EAAE,GAAa;IACrE,IAAI,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,aAAa;YACnB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;gBAC9B,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,SAAS;aAC5B,CAAC,CAAC;;YAEH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,gDAAgD;gBACzD,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,EAAE;aACT,CAAC,CAAC;QAEL,OAAO;IACT,CAAC;IAED,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAC9B,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;QAC9B,KAAK,EAAE,uBAAuB;QAC9B,OAAO,EAAE,gDAAgD;KAC1D,CAAC,CAAC;AACL,CAAC;AAWD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,EAAE,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAE3E,eAAM,CAAC,KAAK,CAAC,GAAG,EAAE;YAChB,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import { NextFunction, Request, Response } from \"express\";\nimport AppError from \"./utils/app-error\";\nimport * as errorControllerHelper from \"./utils/error-handler.helpers\";\nimport { server } from \"../../server\";\n\n/**\n * Error handling middleware for Express.\n *\n * This middleware function handles all errors in the Express application.\n * It checks for the environment (development or production) and sends appropriate error responses\n * based on whether the environment is production or not. It also maps specific errors such as\n * JWT errors, Prisma client errors, and database-related errors to specific helper functions for handling.\n *\n * @param {AppError} err - The error object thrown by the application.\n * @param {Request} req - The Express request object.\n * @param {Response} res - The Express response object.\n * @param {NextFunction} _ - The next middleware function in the chain.\n *\n * @returns {void} - Sends the response with the error details to the client.\n */\nexport default function errorHandler(\n err: AppError,\n req: Request,\n res: Response,\n _: NextFunction\n): void {\n console.error(\"[\\x1b[31mError\\x1b[0m]:\", err);\n\n err.statusCode = err.statusCode || 500;\n err.status = err.status || \"error\";\n\n let error: any = {\n ...err,\n message: err.message,\n stack: err?.stack || undefined,\n };\n\n if (process.env.ARKOS_BUILD === \"true\") delete error?.stack;\n\n if (err.name === \"JsonWebTokenError\")\n error = errorControllerHelper.handleJWTError();\n if (err.name === \"TokenExpiredError\")\n error = errorControllerHelper.handleJWTExpired();\n\n if (err.name === \"PrismaClientValidationError\")\n error = errorControllerHelper.handlePrismaClientValidationError(err);\n if (err.name === \"PrismaClientInitializationError\")\n error = errorControllerHelper.handlePrismaClientInitializationError(err);\n if (err.code === \"P1000\")\n error = errorControllerHelper.handleAuthenticationError(err);\n if (err.code === \"P1001\")\n error = errorControllerHelper.handleServerNotReachableError(err);\n if (err.code === \"P1002\")\n error = errorControllerHelper.handleConnectionTimeoutError(err);\n if (err.code === \"P1003\")\n error = errorControllerHelper.handleDatabaseNotFoundError(err);\n if (err.code === \"P2000\")\n error = errorControllerHelper.handleFieldValueTooLargeError(err);\n if (err.code === \"P2001\")\n error = errorControllerHelper.handleRecordNotFoundError(err);\n if (err.code === \"P2002\")\n error = errorControllerHelper.handleUniqueConstraintError(err);\n if (err.code === \"P2003\")\n error = errorControllerHelper.handleForeignKeyConstraintError(err);\n if (err.code === \"P2004\")\n error = errorControllerHelper.handleConstraintFailedError(err);\n if (err.code === \"P2025\")\n error = errorControllerHelper.handleNonExistingRecord(err);\n if (err.code === \"P3000\")\n error = errorControllerHelper.handleSchemaCreationFailedError(err);\n if (err.code === \"P3001\")\n error = errorControllerHelper.handleMigrationAlreadyAppliedError(err);\n if (err.code === \"P3002\")\n error = errorControllerHelper.handleMigrationScriptFailedError(err);\n if (err.code === \"P3003\")\n error = errorControllerHelper.handleVersionMismatchError(err);\n\n if (err.name === \"NetworkError\")\n error = errorControllerHelper.handleNetworkError(err);\n\n if (process.env.ARKOS_BUILD !== \"true\")\n return sendDevelopmentError(\n {\n ...error,\n message: error.message,\n stack: err.stack,\n originalError: err,\n },\n req,\n res\n );\n\n sendProductionError(error, req, res);\n}\n\n/**\n * Sends a detailed error response in development mode.\n *\n * In development, the error response includes full error details, including\n * the stack trace and the complete error message.\n *\n * @param {AppError} err - The error object.\n * @param {Request} req - The Express request object.\n * @param {Response} res - The Express response object.\n *\n * @returns {void} - Sends the response with the error details to the client.\n */\nfunction sendDevelopmentError(err: any, req: Request, res: Response): void {\n if (req.originalUrl.startsWith(\"/api\"))\n res.status(err.statusCode).json({\n ...err,\n message: err.message.split(\"\\n\")[err.message.split(\"\\n\").length - 1],\n stack: err.stack?.split(\"\\n\"),\n });\n else\n res.status(err.statusCode).json({\n title: \"Internal server error\",\n message: err.message,\n });\n}\n\n/**\n * Sends a generic error response in production mode.\n *\n * In production, sensitive error details (such as stack traces) are not exposed\n * to the client. Only operational errors are shown with a generic message.\n *\n * @param {AppError} err - The error object.\n * @param {Request} req - The Express request object.\n * @param {Response} res - The Express response object.\n *\n * @returns {void} - Sends the response with the error details to the client.\n */\nfunction sendProductionError(err: AppError, req: Request, res: Response): void {\n if (req.originalUrl.startsWith(\"/api\")) {\n if (err.isOperational)\n res.status(err.statusCode).json({\n status: err.status,\n message: err.message,\n meta: err.meta || {},\n code: err.code || \"Unknown\",\n });\n else\n res.status(500).json({\n status: \"error\",\n message: \"Internal server error, please try again later.\",\n code: \"Unknown\",\n meta: {},\n });\n\n return;\n }\n\n if (err.isOperational) {\n res.status(err.statusCode).json({\n title: \"Internal server error\",\n message: err.message,\n code: \"Unknown\",\n });\n return;\n }\n\n res.status(err.statusCode).json({\n title: \"Internal server error\",\n message: \"Internal server error, please try again later.\",\n });\n}\n\n/**\n * Gracefully handles process termination by listening for SIGTERM signal.\n *\n * - In production and staging environments, it will log a shutdown message\n * and attempt to close the server gracefully.\n * - In development or non-production environments, it will immediately exit the process.\n *\n * @returns {void}\n */\nprocess.on(\"SIGTERM\", () => {\n if (process.env.ARKOS_BUILD !== \"true\") {\n process.exit();\n } else {\n console.error(\"SIGTERM RECEIVED in Production. Shutting down gracefully!\");\n\n server.close(() => {\n console.error(\"Process terminated!!!\");\n process.exit();\n });\n }\n});\n"]}
|
|
@@ -17,13 +17,10 @@ class FileUploadService {
|
|
|
17
17
|
constructor(uploadDir, fileSizeLimit = 1024 * 1024 * 5, allowedFileTypes = /.*/, maxCount = 30) {
|
|
18
18
|
this.fileFilter = (_, file, cb) => {
|
|
19
19
|
const extName = this.allowedFileTypes.test(path_1.default.extname(file.originalname).toLowerCase());
|
|
20
|
-
|
|
21
|
-
if (mimeType && extName) {
|
|
20
|
+
if (extName)
|
|
22
21
|
cb(null, true);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
cb(new app_error_1.default("Invalid file type", 400));
|
|
26
|
-
}
|
|
22
|
+
else
|
|
23
|
+
cb(new app_error_1.default(`File type not allowed, allowed files are ${String(this.allowedFileTypes).replaceAll("/", "").split("|").join(", ")}`, 400, "NotAllowedFileType", { filename: file.originalname }));
|
|
27
24
|
};
|
|
28
25
|
uploadDir = uploadDir.startsWith("/") ? uploadDir.substring(1) : uploadDir;
|
|
29
26
|
uploadDir = uploadDir.endsWith("/") ? uploadDir.slice(0, -1) : uploadDir;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.service.js","sourceRoot":"","sources":["../../../../src/modules/file-upload/file-upload.service.ts"],"names":[],"mappings":"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","sourcesContent":["import multer, { StorageEngine } from \"multer\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { NextFunction } from \"express\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { promisify } from \"util\";\nimport { getArkosConfig } from \"../../server\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport {\n ArkosNextFunction,\n ArkosRequest,\n ArkosRequestHandler,\n ArkosResponse,\n} from \"../../types\";\nimport { processFile, processImage } from \"./utils/helpers/file-upload.helpers\";\nimport { removeBothSlashes } from \"../../utils/helpers/text.helpers\";\n\n/**\n * Service to handle file uploads, including single and multiple file uploads,\n * file validation (type, size), and file deletion.\n */\nexport class FileUploadService {\n public readonly uploadDir: string;\n private fileSizeLimit: number;\n private allowedFileTypes: RegExp;\n private storage: StorageEngine;\n private maxCount: number;\n\n /**\n * Constructor to initialize the file uploader service.\n * @param {string} uploadDir - The directory where files will be uploaded.\n * @param {number} fileSizeLimit - The maximum allowed file size.\n * @param {RegExp} allowedFileTypes - The regular expression for allowed file types.\n */\n constructor(\n uploadDir: string,\n fileSizeLimit: number = 1024 * 1024 * 5,\n allowedFileTypes: RegExp = /.*/,\n maxCount: number = 30\n ) {\n uploadDir = uploadDir.startsWith(\"/\") ? uploadDir.substring(1) : uploadDir;\n uploadDir = uploadDir.endsWith(\"/\") ? uploadDir.slice(0, -1) : uploadDir;\n\n this.uploadDir = path.resolve(process.cwd(), `${uploadDir}/`);\n this.fileSizeLimit = fileSizeLimit;\n this.allowedFileTypes = allowedFileTypes;\n this.maxCount = maxCount;\n\n if (!fs.existsSync(this.uploadDir)) {\n fs.mkdirSync(this.uploadDir, { recursive: true });\n }\n\n this.storage = multer.diskStorage({\n destination: (_, _1, cb) => {\n cb(null, this.uploadDir);\n },\n filename: (_, file, cb) => {\n const uniqueSuffix = Date.now() + \"-\" + Math.round(Math.random() * 1e9);\n const ext = path.extname(file.originalname);\n cb(null, `${file.originalname.replace(ext, \"\")}-${uniqueSuffix}${ext}`);\n },\n });\n }\n\n /**\n * Validates the file's type and MIME type.\n * @param {Express.Multer.File} file - The uploaded file.\n * @param {Function} cb - The callback function to indicate if file is valid.\n */\n private fileFilter = (_: any, file: any, cb: any) => {\n const extName = this.allowedFileTypes.test(\n path.extname(file.originalname).toLowerCase()\n );\n const mimeType = this.allowedFileTypes.test(file.mimetype);\n\n if (mimeType && extName) {\n cb(null, true);\n } else {\n cb(new AppError(\"Invalid file type\", 400));\n }\n };\n\n /**\n * Returns the multer upload configuration.\n * @returns {multer.Multer} The multer instance configured for file uploads.\n */\n public getUpload(): multer.Multer {\n return multer({\n storage: this.storage,\n fileFilter: this.fileFilter,\n limits: { fileSize: this.fileSizeLimit },\n });\n }\n\n /**\n * Middleware to handle single file upload.\n * @param {string} [oldFilePath] - The path to the file to delete before uploading.\n * @returns {Function} Middleware function for handling file upload.\n */\n public handleSingleUpload(oldFilePath?: string): ArkosRequestHandler {\n return (req: ArkosRequest, res: ArkosResponse, next: NextFunction) => {\n const upload = this.getUpload().single(this.getFieldName());\n upload(req, res, async (err) => {\n if (err instanceof multer.MulterError) {\n return next(err);\n } else if (err) {\n return next(err);\n }\n\n if (oldFilePath) {\n const { fileUpload: configs } = getArkosConfig();\n\n const filePath = path.resolve(\n process.cwd(),\n removeBothSlashes(configs?.baseUploadDir!),\n removeBothSlashes(oldFilePath)\n );\n try {\n const stats = await promisify(fs.stat)(filePath);\n if (stats) await promisify(fs.unlink)(filePath);\n } catch (err) {\n console.error(err);\n }\n }\n\n next();\n });\n };\n }\n\n /**\n * Middleware to handle multiple file uploads.\n * @returns {Function} Middleware function for handling multiple file uploads.\n */\n public handleMultipleUpload(): ArkosRequestHandler {\n return (req: ArkosRequest, res: ArkosResponse, next: NextFunction) => {\n const upload = this.getUpload().array(this.getFieldName(), this.maxCount);\n upload(req, res, (err) => {\n if (err instanceof multer.MulterError) return next(err);\n else if (err) return next(err);\n next();\n });\n };\n }\n\n /**\n * Middleware to handle deletion of a single file from the filesystem.\n * @param {string} oldFilePath - The path to the file to be deleted.\n * @returns {Function} Middleware function for handling file deletion.\n */\n public handleDeleteSingleFile(oldFilePath: string): ArkosRequestHandler {\n return async (_: ArkosRequest, _1: ArkosResponse, next: NextFunction) => {\n const filePath = path.join(oldFilePath);\n try {\n const stats = await promisify(fs.stat)(filePath);\n if (stats) {\n await promisify(fs.unlink)(filePath);\n }\n } catch (err) {\n console.error(err);\n }\n\n next();\n };\n }\n\n /**\n * Deletes a file based on its URL by identifying the appropriate uploader service\n * @param {string} fileUrl - The URL of the file to delete\n * @returns {Promise<boolean>} - True if deletion successful, false otherwise\n */\n public async deleteFileByUrl(fileUrl: string): Promise<boolean> {\n try {\n // Get configuration values\n const { fileUpload } = getArkosConfig();\n const baseRoute = fileUpload?.baseRoute || \"/api/uploads\";\n\n // Parse the URL to get the path\n let urlPath: string;\n if (fileUrl.startsWith(\"http\")) {\n const url = new URL(fileUrl);\n urlPath = url.pathname;\n } else {\n urlPath = fileUrl;\n }\n\n // Extract the path after the base route\n const baseRouteIndex = urlPath.indexOf(baseRoute);\n if (baseRouteIndex === -1) {\n throw new AppError(\"Invalid file URL: base route not found\", 400);\n }\n\n const pathAfterBaseRoute = urlPath.substring(\n baseRouteIndex + baseRoute.length\n );\n const cleanPath = pathAfterBaseRoute.startsWith(\"/\")\n ? pathAfterBaseRoute.substring(1)\n : pathAfterBaseRoute;\n\n // Determine file type and file name\n const fileTypes = [\"images\", \"videos\", \"documents\", \"files\"];\n let fileType: string | null = null;\n let fileName: string | null = null;\n\n for (const type of fileTypes) {\n const typeIndex = cleanPath.indexOf(type + \"/\");\n if (typeIndex !== -1) {\n fileType = type;\n fileName = cleanPath.substring(typeIndex + type.length + 1);\n break;\n }\n }\n\n if (!fileType || !fileName) {\n throw new AppError(\n \"Unable to determine file type or file name from URL\",\n 400\n );\n }\n\n // Get the appropriate uploader service based on file type\n const {\n documentUploadService,\n fileUploadService,\n imageUploadService,\n videoUploadService,\n } = getFileUploadServices();\n\n let filePath: string;\n switch (fileType) {\n case \"images\":\n filePath = path.join(imageUploadService.uploadDir, fileName);\n break;\n case \"videos\":\n filePath = path.join(videoUploadService.uploadDir, fileName);\n break;\n case \"documents\":\n filePath = path.join(documentUploadService.uploadDir, fileName);\n break;\n case \"files\":\n filePath = path.join(fileUploadService.uploadDir, fileName);\n break;\n default:\n throw new AppError(`Unsupported file type: ${fileType}`, 400);\n }\n\n // Delete the file\n\n await promisify(fs.stat)(filePath);\n await promisify(fs.unlink)(filePath);\n\n return true;\n } catch (error: any) {\n if (error instanceof AppError) {\n throw error;\n }\n\n if (error.code === \"ENOENT\") {\n throw new AppError(\"File not found\", 404);\n }\n\n throw new AppError(`Failed to delete file: ${error.message}`, 500);\n }\n }\n\n private getFieldName() {\n let fieldName = \"files\";\n if (this.uploadDir.endsWith(\"images\") || this.uploadDir.endsWith(\"images/\"))\n fieldName = \"images\";\n if (this.uploadDir.endsWith(\"videos\") || this.uploadDir.endsWith(\"videos/\"))\n fieldName = \"videos\";\n if (\n this.uploadDir.endsWith(\"documents\") ||\n this.uploadDir.endsWith(\"documents/\")\n )\n fieldName = \"documents\";\n if (this.uploadDir.endsWith(\"files\") || this.uploadDir.endsWith(\"files/\"))\n fieldName = \"files\";\n return fieldName;\n }\n\n /**\n * Handles the upload process and returns the full URLs of uploaded files\n * @param {ArkosRequest} req - Arkos request object containing the files\n * @param {ArkosResponse} res - Arkos response object\n * @param {object} options - Optional parameters for image processing\n * @returns {Promise<string|string[]>} URL or array of URLs to the uploaded files\n */\n public async upload(\n req: ArkosRequest,\n res: ArkosResponse,\n next: ArkosNextFunction,\n options: {\n format?: string;\n width?: number;\n height?: number;\n resizeTo?: number;\n } = {}\n ): Promise<string | string[] | null> {\n const { fileUpload } = getArkosConfig();\n fileUpload?.baseRoute || \"/api/uploads\";\n\n return new Promise((resolve, reject) => {\n // Determine if it's a single or multiple file upload\n const isMultiple = Array.isArray(req.query.multiple)\n ? req.query.multiple[0] == \"true\"\n : req.query.multiple == \"true\";\n\n // Use appropriate upload handler\n const uploadHandler = isMultiple\n ? this.getUpload().array(this.getFieldName(), this.maxCount)\n : this.getUpload().single(this.getFieldName());\n\n uploadHandler(req, res, async (err) => {\n if (err) return reject(err);\n\n try {\n // Determine the base URL for file access\n const protocol = req.get(\"host\")?.includes?.(\"localhost\")\n ? \"http\"\n : \"https\";\n `${protocol}://${req.get(\"host\")}`;\n\n // Get file type from uploadDir path\n const dirParts = this.uploadDir.split(\"/\");\n (this.uploadDir.endsWith(\"/\")\n ? dirParts[dirParts.length - 2]\n : dirParts[dirParts.length - 1]) || \"files\";\n\n let data;\n if (req.files && Array.isArray(req.files) && req.files.length > 0) {\n const isImageUpload = this.uploadDir?.includes?.(\"/images\");\n if (isImageUpload) {\n data = await Promise.all(\n req.files.map((file) =>\n processImage(req, next, file.path, options)\n )\n );\n } else {\n data = await Promise.all(\n req.files.map((file) => processFile(req, file.path))\n );\n }\n // Filter out any null values from failed processing\n data = data.filter((url) => url !== null);\n } else if (req.file) {\n // Process a single file\n const isImageUpload = this.uploadDir?.includes?.(\"/images\");\n if (isImageUpload) {\n data = await processImage(req, next, req.file.path, options);\n } else {\n data = await processFile(req, req.file.path);\n }\n } else {\n return reject(new AppError(\"No file uploaded\", 400));\n }\n\n resolve(data);\n } catch (error) {\n reject(error);\n }\n });\n });\n }\n\n /**\n * Deletes a file based on filename and file type from request parameters\n * @param {string} fileName - The name of the file to delete\n * @returns {Promise<boolean>} - True if deletion successful, false otherwise\n */\n public async deleteFileByName(\n fileName: string,\n fileType: \"images\" | \"videos\" | \"documents\" | \"files\"\n ): Promise<boolean> {\n try {\n if (!fileType) throw new AppError(\"File type parameter is required\", 400);\n\n const validFileTypes = [\"images\", \"videos\", \"documents\", \"files\"];\n if (!validFileTypes.includes(fileType)) {\n throw new AppError(\n `Invalid file type: ${fileType}. Must be one of: ${validFileTypes.join(\n \", \"\n )}`,\n 400\n );\n }\n\n // Get the appropriate uploader service based on file type\n const {\n documentUploadService,\n fileUploadService,\n imageUploadService,\n videoUploadService,\n } = getFileUploadServices();\n\n let targetService: FileUploadService;\n switch (fileType) {\n case \"images\":\n targetService = imageUploadService;\n break;\n case \"videos\":\n targetService = videoUploadService;\n break;\n case \"documents\":\n targetService = documentUploadService;\n break;\n case \"files\":\n targetService = fileUploadService;\n break;\n default:\n throw new AppError(`Unsupported file type: ${fileType}`, 400);\n }\n\n // Construct the full file path\n const filePath = path.join(targetService.uploadDir, fileName);\n\n // Check if file exists and delete it\n await promisify(fs.stat)(filePath);\n await promisify(fs.unlink)(filePath);\n\n return true;\n } catch (error: any) {\n if (error instanceof AppError) {\n throw error;\n }\n\n if (error.code === \"ENOENT\") {\n throw new AppError(\"File not found\", 404);\n }\n\n throw new AppError(`Failed to delete file: ${error.message}`, 500);\n }\n }\n}\n\n/**\n * Creates and returns all file uploader services based on config\n * @returns Object containing all specialized file uploader services\n */\nexport const getFileUploadServices = () => {\n const { fileUpload } = getArkosConfig();\n const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n const restrictions = fileUpload?.restrictions\n ? deepmerge(fileUploadDefaultRestrictions, fileUpload.restrictions)\n : fileUploadDefaultRestrictions;\n\n /**\n * Specialized file uploader service for handling image uploads.\n */\n const imageUploadService = new FileUploadService(\n `${baseUploadDir}/images`,\n restrictions.images.maxSize,\n restrictions.images.supportedFilesRegex,\n restrictions.images.maxCount\n );\n\n /**\n * Specialized file uploader service for handling video uploads.\n */\n const videoUploadService = new FileUploadService(\n `${baseUploadDir}/videos`,\n restrictions.videos.maxSize,\n restrictions.videos.supportedFilesRegex,\n restrictions.videos.maxCount\n );\n\n /**\n * Specialized file uploader service for handling document uploads.\n */\n const documentUploadService = new FileUploadService(\n `${baseUploadDir}/documents`,\n restrictions.documents.maxSize,\n restrictions.documents.supportedFilesRegex,\n restrictions.documents.maxCount\n );\n\n /**\n * Generic file uploader service for handling all file uploads.\n */\n const fileUploadService = new FileUploadService(\n `${baseUploadDir}/files`,\n restrictions.files.maxSize,\n restrictions.files.supportedFilesRegex,\n restrictions.files.maxCount\n );\n\n return {\n imageUploadService,\n videoUploadService,\n documentUploadService,\n fileUploadService,\n };\n};\n\nexport const fileUploadDefaultRestrictions = {\n images: {\n maxCount: 30,\n maxSize: 1024 * 1024 * 15, // 15 MB\n supportedFilesRegex:\n /jpeg|jpg|png|gif|webp|svg|bmp|tiff|heif|heic|ico|jfif|raw|cr2|nef|orf|sr2|arw|dng|pef|raf|rw2|psd|ai|eps|xcf|jxr|wdp|hdp|jp2|j2k|jpf|jpx|jpm|mj2|avif/,\n },\n videos: {\n maxCount: 10,\n maxSize: 1024 * 1024 * 5096, // 5 GB\n supportedFilesRegex:\n /mp4|avi|mov|mkv|flv|wmv|webm|mpg|mpeg|3gp|m4v|ts|rm|rmvb|vob|ogv|dv|qt|asf|m2ts|mts|divx|f4v|swf|mxf|roq|nsv|mvb|svi|mpe|m2v|mp2|mpv|h264|h265|hevc/,\n },\n documents: {\n maxCount: 30,\n maxSize: 1024 * 1024 * 50, // 50 MB\n supportedFilesRegex:\n /pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odg|odp|txt|rtf|csv|epub|md|tex|pages|numbers|key|xml|json|yaml|yml|ini|cfg|conf|log|html|htm|xhtml|djvu|mobi|azw|azw3|fb2|lit|ps|wpd|wps|dot|dotx|xlt|xltx|pot|potx|oft|one|onetoc2|opf|oxps|hwp/,\n },\n files: {\n maxCount: 10,\n maxSize: 1024 * 1024 * 5096, // 5 GB\n supportedFilesRegex: /.*/,\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"file-upload.service.js","sourceRoot":"","sources":["../../../../src/modules/file-upload/file-upload.service.ts"],"names":[],"mappings":"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","sourcesContent":["import multer, { StorageEngine } from \"multer\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { NextFunction } from \"express\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { promisify } from \"util\";\nimport { getArkosConfig } from \"../../server\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport {\n ArkosNextFunction,\n ArkosRequest,\n ArkosRequestHandler,\n ArkosResponse,\n} from \"../../types\";\nimport { processFile, processImage } from \"./utils/helpers/file-upload.helpers\";\nimport { removeBothSlashes } from \"../../utils/helpers/text.helpers\";\n\n/**\n * Service to handle file uploads, including single and multiple file uploads,\n * file validation (type, size), and file deletion.\n */\nexport class FileUploadService {\n public readonly uploadDir: string;\n private fileSizeLimit: number;\n private allowedFileTypes: RegExp;\n private storage: StorageEngine;\n private maxCount: number;\n\n /**\n * Constructor to initialize the file uploader service.\n * @param {string} uploadDir - The directory where files will be uploaded.\n * @param {number} fileSizeLimit - The maximum allowed file size.\n * @param {RegExp} allowedFileTypes - The regular expression for allowed file types.\n */\n constructor(\n uploadDir: string,\n fileSizeLimit: number = 1024 * 1024 * 5,\n allowedFileTypes: RegExp = /.*/,\n maxCount: number = 30\n ) {\n uploadDir = uploadDir.startsWith(\"/\") ? uploadDir.substring(1) : uploadDir;\n uploadDir = uploadDir.endsWith(\"/\") ? uploadDir.slice(0, -1) : uploadDir;\n\n this.uploadDir = path.resolve(process.cwd(), `${uploadDir}/`);\n this.fileSizeLimit = fileSizeLimit;\n this.allowedFileTypes = allowedFileTypes;\n this.maxCount = maxCount;\n\n if (!fs.existsSync(this.uploadDir)) {\n fs.mkdirSync(this.uploadDir, { recursive: true });\n }\n\n this.storage = multer.diskStorage({\n destination: (_, _1, cb) => {\n cb(null, this.uploadDir);\n },\n filename: (_, file, cb) => {\n const uniqueSuffix = Date.now() + \"-\" + Math.round(Math.random() * 1e9);\n const ext = path.extname(file.originalname);\n cb(null, `${file.originalname.replace(ext, \"\")}-${uniqueSuffix}${ext}`);\n },\n });\n }\n\n /**\n * Validates the file's type and MIME type.\n * @param {Express.Multer.File} file - The uploaded file.\n * @param {Function} cb - The callback function to indicate if file is valid.\n */\n private fileFilter = (_: any, file: any, cb: any) => {\n const extName = this.allowedFileTypes.test(\n path.extname(file.originalname).toLowerCase()\n );\n\n if (extName) cb(null, true);\n else\n cb(\n new AppError(\n `File type not allowed, allowed files are ${String(this.allowedFileTypes).replaceAll(\"/\", \"\").split(\"|\").join(\", \")}`,\n 400,\n \"NotAllowedFileType\",\n { filename: file.originalname }\n )\n );\n };\n\n /**\n * Returns the multer upload configuration.\n * @returns {multer.Multer} The multer instance configured for file uploads.\n */\n public getUpload(): multer.Multer {\n return multer({\n storage: this.storage,\n fileFilter: this.fileFilter,\n limits: { fileSize: this.fileSizeLimit },\n });\n }\n\n /**\n * Middleware to handle single file upload.\n * @param {string} [oldFilePath] - The path to the file to delete before uploading.\n * @returns {Function} Middleware function for handling file upload.\n */\n public handleSingleUpload(oldFilePath?: string): ArkosRequestHandler {\n return (req: ArkosRequest, res: ArkosResponse, next: NextFunction) => {\n const upload = this.getUpload().single(this.getFieldName());\n upload(req, res, async (err) => {\n if (err instanceof multer.MulterError) {\n return next(err);\n } else if (err) {\n return next(err);\n }\n\n if (oldFilePath) {\n const { fileUpload: configs } = getArkosConfig();\n\n const filePath = path.resolve(\n process.cwd(),\n removeBothSlashes(configs?.baseUploadDir!),\n removeBothSlashes(oldFilePath)\n );\n try {\n const stats = await promisify(fs.stat)(filePath);\n if (stats) await promisify(fs.unlink)(filePath);\n } catch (err) {\n console.error(err);\n }\n }\n\n next();\n });\n };\n }\n\n /**\n * Middleware to handle multiple file uploads.\n * @returns {Function} Middleware function for handling multiple file uploads.\n */\n public handleMultipleUpload(): ArkosRequestHandler {\n return (req: ArkosRequest, res: ArkosResponse, next: NextFunction) => {\n const upload = this.getUpload().array(this.getFieldName(), this.maxCount);\n upload(req, res, (err) => {\n if (err instanceof multer.MulterError) return next(err);\n else if (err) return next(err);\n next();\n });\n };\n }\n\n /**\n * Middleware to handle deletion of a single file from the filesystem.\n * @param {string} oldFilePath - The path to the file to be deleted.\n * @returns {Function} Middleware function for handling file deletion.\n */\n public handleDeleteSingleFile(oldFilePath: string): ArkosRequestHandler {\n return async (_: ArkosRequest, _1: ArkosResponse, next: NextFunction) => {\n const filePath = path.join(oldFilePath);\n try {\n const stats = await promisify(fs.stat)(filePath);\n if (stats) {\n await promisify(fs.unlink)(filePath);\n }\n } catch (err) {\n console.error(err);\n }\n\n next();\n };\n }\n\n /**\n * Deletes a file based on its URL by identifying the appropriate uploader service\n * @param {string} fileUrl - The URL of the file to delete\n * @returns {Promise<boolean>} - True if deletion successful, false otherwise\n */\n public async deleteFileByUrl(fileUrl: string): Promise<boolean> {\n try {\n // Get configuration values\n const { fileUpload } = getArkosConfig();\n const baseRoute = fileUpload?.baseRoute || \"/api/uploads\";\n\n // Parse the URL to get the path\n let urlPath: string;\n if (fileUrl.startsWith(\"http\")) {\n const url = new URL(fileUrl);\n urlPath = url.pathname;\n } else {\n urlPath = fileUrl;\n }\n\n // Extract the path after the base route\n const baseRouteIndex = urlPath.indexOf(baseRoute);\n if (baseRouteIndex === -1) {\n throw new AppError(\"Invalid file URL: base route not found\", 400);\n }\n\n const pathAfterBaseRoute = urlPath.substring(\n baseRouteIndex + baseRoute.length\n );\n const cleanPath = pathAfterBaseRoute.startsWith(\"/\")\n ? pathAfterBaseRoute.substring(1)\n : pathAfterBaseRoute;\n\n // Determine file type and file name\n const fileTypes = [\"images\", \"videos\", \"documents\", \"files\"];\n let fileType: string | null = null;\n let fileName: string | null = null;\n\n for (const type of fileTypes) {\n const typeIndex = cleanPath.indexOf(type + \"/\");\n if (typeIndex !== -1) {\n fileType = type;\n fileName = cleanPath.substring(typeIndex + type.length + 1);\n break;\n }\n }\n\n if (!fileType || !fileName) {\n throw new AppError(\n \"Unable to determine file type or file name from URL\",\n 400\n );\n }\n\n // Get the appropriate uploader service based on file type\n const {\n documentUploadService,\n fileUploadService,\n imageUploadService,\n videoUploadService,\n } = getFileUploadServices();\n\n let filePath: string;\n switch (fileType) {\n case \"images\":\n filePath = path.join(imageUploadService.uploadDir, fileName);\n break;\n case \"videos\":\n filePath = path.join(videoUploadService.uploadDir, fileName);\n break;\n case \"documents\":\n filePath = path.join(documentUploadService.uploadDir, fileName);\n break;\n case \"files\":\n filePath = path.join(fileUploadService.uploadDir, fileName);\n break;\n default:\n throw new AppError(`Unsupported file type: ${fileType}`, 400);\n }\n\n // Delete the file\n\n await promisify(fs.stat)(filePath);\n await promisify(fs.unlink)(filePath);\n\n return true;\n } catch (error: any) {\n if (error instanceof AppError) {\n throw error;\n }\n\n if (error.code === \"ENOENT\") {\n throw new AppError(\"File not found\", 404);\n }\n\n throw new AppError(`Failed to delete file: ${error.message}`, 500);\n }\n }\n\n private getFieldName() {\n let fieldName = \"files\";\n if (this.uploadDir.endsWith(\"images\") || this.uploadDir.endsWith(\"images/\"))\n fieldName = \"images\";\n if (this.uploadDir.endsWith(\"videos\") || this.uploadDir.endsWith(\"videos/\"))\n fieldName = \"videos\";\n if (\n this.uploadDir.endsWith(\"documents\") ||\n this.uploadDir.endsWith(\"documents/\")\n )\n fieldName = \"documents\";\n if (this.uploadDir.endsWith(\"files\") || this.uploadDir.endsWith(\"files/\"))\n fieldName = \"files\";\n return fieldName;\n }\n\n /**\n * Handles the upload process and returns the full URLs of uploaded files\n * @param {ArkosRequest} req - Arkos request object containing the files\n * @param {ArkosResponse} res - Arkos response object\n * @param {object} options - Optional parameters for image processing\n * @returns {Promise<string|string[]>} URL or array of URLs to the uploaded files\n */\n public async upload(\n req: ArkosRequest,\n res: ArkosResponse,\n next: ArkosNextFunction,\n options: {\n format?: string;\n width?: number;\n height?: number;\n resizeTo?: number;\n } = {}\n ): Promise<string | string[] | null> {\n const { fileUpload } = getArkosConfig();\n fileUpload?.baseRoute || \"/api/uploads\";\n\n return new Promise((resolve, reject) => {\n // Determine if it's a single or multiple file upload\n const isMultiple = Array.isArray(req.query.multiple)\n ? req.query.multiple[0] == \"true\"\n : req.query.multiple == \"true\";\n\n // Use appropriate upload handler\n const uploadHandler = isMultiple\n ? this.getUpload().array(this.getFieldName(), this.maxCount)\n : this.getUpload().single(this.getFieldName());\n\n uploadHandler(req, res, async (err) => {\n if (err) return reject(err);\n\n try {\n // Determine the base URL for file access\n const protocol = req.get(\"host\")?.includes?.(\"localhost\")\n ? \"http\"\n : \"https\";\n `${protocol}://${req.get(\"host\")}`;\n\n // Get file type from uploadDir path\n const dirParts = this.uploadDir.split(\"/\");\n (this.uploadDir.endsWith(\"/\")\n ? dirParts[dirParts.length - 2]\n : dirParts[dirParts.length - 1]) || \"files\";\n\n let data;\n if (req.files && Array.isArray(req.files) && req.files.length > 0) {\n const isImageUpload = this.uploadDir?.includes?.(\"/images\");\n if (isImageUpload) {\n data = await Promise.all(\n req.files.map((file) =>\n processImage(req, next, file.path, options)\n )\n );\n } else {\n data = await Promise.all(\n req.files.map((file) => processFile(req, file.path))\n );\n }\n // Filter out any null values from failed processing\n data = data.filter((url) => url !== null);\n } else if (req.file) {\n // Process a single file\n const isImageUpload = this.uploadDir?.includes?.(\"/images\");\n if (isImageUpload) {\n data = await processImage(req, next, req.file.path, options);\n } else {\n data = await processFile(req, req.file.path);\n }\n } else {\n return reject(new AppError(\"No file uploaded\", 400));\n }\n\n resolve(data);\n } catch (error) {\n reject(error);\n }\n });\n });\n }\n\n /**\n * Deletes a file based on filename and file type from request parameters\n * @param {string} fileName - The name of the file to delete\n * @returns {Promise<boolean>} - True if deletion successful, false otherwise\n */\n public async deleteFileByName(\n fileName: string,\n fileType: \"images\" | \"videos\" | \"documents\" | \"files\"\n ): Promise<boolean> {\n try {\n if (!fileType) throw new AppError(\"File type parameter is required\", 400);\n\n const validFileTypes = [\"images\", \"videos\", \"documents\", \"files\"];\n if (!validFileTypes.includes(fileType)) {\n throw new AppError(\n `Invalid file type: ${fileType}. Must be one of: ${validFileTypes.join(\n \", \"\n )}`,\n 400\n );\n }\n\n // Get the appropriate uploader service based on file type\n const {\n documentUploadService,\n fileUploadService,\n imageUploadService,\n videoUploadService,\n } = getFileUploadServices();\n\n let targetService: FileUploadService;\n switch (fileType) {\n case \"images\":\n targetService = imageUploadService;\n break;\n case \"videos\":\n targetService = videoUploadService;\n break;\n case \"documents\":\n targetService = documentUploadService;\n break;\n case \"files\":\n targetService = fileUploadService;\n break;\n default:\n throw new AppError(`Unsupported file type: ${fileType}`, 400);\n }\n\n // Construct the full file path\n const filePath = path.join(targetService.uploadDir, fileName);\n\n // Check if file exists and delete it\n await promisify(fs.stat)(filePath);\n await promisify(fs.unlink)(filePath);\n\n return true;\n } catch (error: any) {\n if (error instanceof AppError) {\n throw error;\n }\n\n if (error.code === \"ENOENT\") {\n throw new AppError(\"File not found\", 404);\n }\n\n throw new AppError(`Failed to delete file: ${error.message}`, 500);\n }\n }\n}\n\n/**\n * Creates and returns all file uploader services based on config\n * @returns Object containing all specialized file uploader services\n */\nexport const getFileUploadServices = () => {\n const { fileUpload } = getArkosConfig();\n const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n const restrictions = fileUpload?.restrictions\n ? deepmerge(fileUploadDefaultRestrictions, fileUpload.restrictions)\n : fileUploadDefaultRestrictions;\n\n /**\n * Specialized file uploader service for handling image uploads.\n */\n const imageUploadService = new FileUploadService(\n `${baseUploadDir}/images`,\n restrictions.images.maxSize,\n restrictions.images.supportedFilesRegex,\n restrictions.images.maxCount\n );\n\n /**\n * Specialized file uploader service for handling video uploads.\n */\n const videoUploadService = new FileUploadService(\n `${baseUploadDir}/videos`,\n restrictions.videos.maxSize,\n restrictions.videos.supportedFilesRegex,\n restrictions.videos.maxCount\n );\n\n /**\n * Specialized file uploader service for handling document uploads.\n */\n const documentUploadService = new FileUploadService(\n `${baseUploadDir}/documents`,\n restrictions.documents.maxSize,\n restrictions.documents.supportedFilesRegex,\n restrictions.documents.maxCount\n );\n\n /**\n * Generic file uploader service for handling all file uploads.\n */\n const fileUploadService = new FileUploadService(\n `${baseUploadDir}/files`,\n restrictions.files.maxSize,\n restrictions.files.supportedFilesRegex,\n restrictions.files.maxCount\n );\n\n return {\n imageUploadService,\n videoUploadService,\n documentUploadService,\n fileUploadService,\n };\n};\n\nexport const fileUploadDefaultRestrictions = {\n images: {\n maxCount: 30,\n maxSize: 1024 * 1024 * 15, // 15 MB\n supportedFilesRegex:\n /jpeg|jpg|png|gif|webp|svg|bmp|tiff|heif|heic|ico|jfif|raw|cr2|nef|orf|sr2|arw|dng|pef|raf|rw2|psd|ai|eps|xcf|jxr|wdp|hdp|jp2|j2k|jpf|jpx|jpm|mj2|avif/,\n },\n videos: {\n maxCount: 10,\n maxSize: 1024 * 1024 * 5096, // 5 GB\n supportedFilesRegex:\n /mp4|avi|mov|mkv|flv|wmv|webm|mpg|mpeg|3gp|m4v|ts|rm|rmvb|vob|ogv|dv|qt|asf|m2ts|mts|divx|f4v|swf|mxf|roq|nsv|mvb|svi|mpe|m2v|mp2|mpv|h264|h265|hevc/,\n },\n documents: {\n maxCount: 30,\n maxSize: 1024 * 1024 * 50, // 50 MB\n supportedFilesRegex:\n /pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odg|odp|txt|rtf|csv|epub|md|tex|pages|numbers|key|xml|json|yaml|yml|ini|cfg|conf|log|html|htm|xhtml|djvu|mobi|azw|azw3|fb2|lit|ps|wpd|wps|dot|dotx|xlt|xltx|pot|potx|oft|one|onetoc2|opf|oxps|hwp/,\n },\n files: {\n maxCount: 10,\n maxSize: 1024 * 1024 * 5096, // 5 GB\n supportedFilesRegex: /.*/,\n },\n};\n"]}
|
|
@@ -16,8 +16,9 @@ const BUILD_DIR = ".build";
|
|
|
16
16
|
const MODULE_TYPES = ["cjs", "esm"];
|
|
17
17
|
function buildCommand(options = {}) {
|
|
18
18
|
const fileExt = (0, fs_helpers_1.getUserFileExtension)();
|
|
19
|
-
process.env.NODE_ENV
|
|
20
|
-
|
|
19
|
+
if (process.env.NODE_ENV === "test" || !process.env.NODE_ENV)
|
|
20
|
+
process.env.NODE_ENV = "production";
|
|
21
|
+
process.env.ARKOS_BUILD = "true";
|
|
21
22
|
const envFiles = (0, dotenv_helpers_1.loadEnvironmentVariables)();
|
|
22
23
|
const moduleType = validateModuleType(options.module);
|
|
23
24
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../../src/utils/cli/build.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\nimport fs from \"fs\";\nimport { execSync } from \"child_process\";\nimport { fullCleanCwd, getUserFileExtension } from \"../helpers/fs.helpers\";\nimport { loadEnvironmentVariables } from \"../dotenv.helpers\";\nimport { getVersion } from \"./utils/cli.helpers\";\nimport { detectPackageManagerFromUserAgent } from \"../helpers/global.helpers\";\nimport sheu from \"../sheu\";\n\n// Constants\nconst BUILD_DIR = \".build\";\nconst MODULE_TYPES = [\"cjs\", \"esm\"] as const;\ntype ModuleType = (typeof MODULE_TYPES)[number];\n\ninterface BuildOptions {\n config?: string;\n module?: string;\n}\n\n/**\n * Main build function for the arkos CLI\n */\nexport function buildCommand(options: BuildOptions = {}) {\n const fileExt = getUserFileExtension();\n process.env.NODE_ENV = \"production\";\n process.env.NODE_ENV = \"true\";\n\n const envFiles = loadEnvironmentVariables();\n const moduleType = validateModuleType(options.module);\n\n try {\n console.info(` \\x1b[1m\\x1b[36m Arkos.js ${getVersion()}\\x1b[0m`);\n console.info(\n ` - Environments: ${fullCleanCwd(envFiles?.join(\", \") || \"\")\n .replaceAll(`${process.cwd()}/`, \"\")\n .replaceAll(\"/\", \"\")}`\n );\n\n console.info(`\\n Creating an optimized production build...`);\n\n ensureBuildDir();\n\n // Detect project type\n\n if (fileExt === \"ts\") {\n buildTypeScriptProject(options, moduleType);\n } else {\n buildJavaScriptProject(options, moduleType);\n }\n\n const packageManger = detectPackageManagerFromUserAgent();\n\n console.info(`\\n\\x1b[1m\\x1b[32m Build complete!\\x1b[0m\\n`);\n console.info(` \\x1b[1mNext step:\\x1b[0m`);\n console.info(\n ` Run it using \\x1b[1m\\x1b[36m${packageManger} run start\\x1b[0m\\n`\n );\n } catch (err: any) {\n console.info(\"\");\n sheu.error(`Build failed: ${err?.message}`);\n console.error(err);\n process.exit(1);\n }\n}\n\n/**\n * Validates and normalizes module type option\n */\nfunction validateModuleType(moduleType?: string): ModuleType {\n if (!moduleType) return \"cjs\";\n\n const normalizedType = moduleType.toLowerCase();\n\n // Map common terms to our module types\n if (normalizedType === \"cjs\" || normalizedType === \"commonjs\") {\n return \"cjs\";\n } else if (\n [\"esm\", \"es\", \"es2020\", \"esnext\", \"module\"].includes(normalizedType)\n ) {\n return \"esm\";\n }\n\n // Default to CJS if unrecognized\n console.warn(\n `⚠️ Unrecognized module type \"${moduleType}\", defaulting to \"cjs\"`\n );\n return \"cjs\";\n}\n\n/**\n * Ensure the build directory exists\n */\nfunction ensureBuildDir() {\n if (!fs.existsSync(BUILD_DIR)) {\n fs.mkdirSync(BUILD_DIR, { recursive: true });\n }\n\n // Create module-specific subdirectories\n for (const moduleType of MODULE_TYPES) {\n const moduleDir = path.join(BUILD_DIR, moduleType);\n if (!fs.existsSync(moduleDir)) {\n fs.mkdirSync(moduleDir, { recursive: true });\n }\n }\n}\n\n/**\n * Build a TypeScript project\n */\nfunction buildTypeScriptProject(options: BuildOptions, moduleType: ModuleType) {\n // Read the user's tsconfig.json\n const tsconfigPath = path.join(\n process.cwd(),\n options.config || \"tsconfig.json\"\n );\n let tsconfig: any = {};\n\n try {\n if (fs.existsSync(tsconfigPath)) {\n const tsconfigContent = fs.readFileSync(tsconfigPath, \"utf8\");\n tsconfig = JSON.parse(tsconfigContent);\n }\n } catch (error) {\n console.error(\"❌ Error reading tsconfig.json:\", error);\n // Continue with default config\n }\n\n // Create a custom tsconfig that outputs to our build directory with the correct module type\n const tempTsconfig = {\n ...tsconfig,\n compilerOptions: {\n ...(tsconfig.compilerOptions || {}),\n rootDir: \".\",\n outDir: path.join(`./${BUILD_DIR}`),\n // module: moduleType === \"esm\" ? \"ESNext\" : \"CommonJS\",\n },\n };\n\n const tempTsconfigPath = path.join(\n process.cwd(),\n `tsconfig.arkos-build.json`\n );\n fs.writeFileSync(tempTsconfigPath, JSON.stringify(tempTsconfig, null, 2));\n\n try {\n execSync(`npx trash ${BUILD_DIR} && npx tsc -p ${tempTsconfigPath}`, {\n stdio: \"inherit\",\n cwd: process.cwd(),\n });\n\n copyAllNonSourceFiles(moduleType, [\".ts\", \".tsx\"]);\n\n // Clean up temp config\n cleanupTempConfig(tempTsconfigPath);\n } catch (error) {\n cleanupTempConfig(tempTsconfigPath);\n throw error;\n }\n}\n\n/**\n * Build a JavaScript project\n */\nfunction buildJavaScriptProject(_: BuildOptions, moduleType: ModuleType) {\n const targetDir = path.join(BUILD_DIR);\n\n try {\n if (moduleType === \"esm\") {\n execSync(\n `npx copyfiles -u 0 \"src/**/*.js\" \"src/**/*.jsx\" \"src/**/*.mjs\" ${targetDir}`,\n {\n stdio: \"inherit\",\n cwd: process.cwd(),\n }\n );\n\n console.info(\"Note: .cjs files are skipped in ESM build\");\n } else {\n execSync(\n `npx copyfiles -u 0 \"src/**/*.js\" \"src/**/*.jsx\" \"src/**/*.cjs\" \"src/**/*.mjs\" ${targetDir}`,\n {\n stdio: \"inherit\",\n cwd: process.cwd(),\n }\n );\n }\n\n copyAllNonSourceFiles(moduleType, [\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".ts\",\n \".tsx\",\n ]);\n\n // Create appropriate package.json in the build directory\n createModulePackageJson(moduleType);\n } catch (error) {\n console.error(\"❌ Error building JavaScript project:\", error);\n throw error;\n }\n}\n\n/**\n * Copy all non-source code files to the build directory\n * This function will copy everything except the specified source file extensions\n */\nfunction copyAllNonSourceFiles(_: ModuleType, skipExtensions: string[]) {\n const targetDir = path.join(BUILD_DIR);\n const sourceDir = \"src\";\n\n try {\n // Recursive function to copy files\n function copyDirRecursive(dir: string) {\n if (!fs.existsSync(dir)) return;\n\n const items = fs.readdirSync(dir);\n\n for (const item of items) {\n const sourcePath = path.join(dir, item);\n const targetPath = path.join(\n targetDir,\n dir.replace(sourceDir, \"\"),\n item\n );\n\n // Get file stats\n const stats = fs.statSync(sourcePath);\n\n if (stats.isDirectory()) {\n // Ensure target directory exists\n if (!fs.existsSync(targetPath)) {\n fs.mkdirSync(targetPath, { recursive: true });\n }\n // Recurse into subdirectory\n copyDirRecursive(sourcePath);\n } else if (stats.isFile()) {\n // Check if this is a file we should skip\n const ext = path.extname(item).toLowerCase();\n if (!skipExtensions.includes(ext)) {\n // Ensure the target directory exists\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n // Copy the file\n fs.copyFileSync(sourcePath, targetPath);\n }\n }\n }\n }\n\n // Start copying from src directory\n copyDirRecursive(sourceDir);\n\n // Copy project root files if needed\n const rootFilesToCopy = [\"README.md\", \"LICENSE\"];\n\n for (const file of rootFilesToCopy) {\n if (fs.existsSync(path.join(process.cwd(), file))) {\n fs.copyFileSync(\n path.join(process.cwd(), file),\n path.join(targetDir, file)\n );\n }\n }\n\n // console.info(`Copied all non-source files to ${targetDir}`);\n } catch (error) {\n console.warn(\"Warning: Error copying project files:\", error);\n console.error(error);\n }\n}\n\n/**\n * Create appropriate package.json in the build directory\n */\nfunction createModulePackageJson(moduleType: ModuleType) {\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n return;\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\"));\n const buildPackageJson: any = {\n name: packageJson.name,\n version: packageJson.version,\n description: packageJson.description,\n main: \"index.js\",\n dependencies: packageJson.dependencies,\n };\n\n // Set appropriate type field for ESM\n if (moduleType === \"esm\") {\n buildPackageJson.type = \"module\";\n }\n\n const targetDir = path.join(BUILD_DIR, moduleType);\n fs.writeFileSync(\n path.join(targetDir, \"package.json\"),\n JSON.stringify(buildPackageJson, null, 2)\n );\n } catch (error) {\n console.warn(\n \"Warning: Failed to create module-specific package.json\",\n error\n );\n }\n}\n\n/**\n * Clean up temporary tsconfig\n */\nfunction cleanupTempConfig(configPath: string) {\n try {\n if (fs.existsSync(configPath)) fs.unlinkSync(configPath);\n } catch (error) {\n console.warn(\"Warning: Error cleaning up temporary config:\", error);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../../src/utils/cli/build.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\nimport fs from \"fs\";\nimport { execSync } from \"child_process\";\nimport { fullCleanCwd, getUserFileExtension } from \"../helpers/fs.helpers\";\nimport { loadEnvironmentVariables } from \"../dotenv.helpers\";\nimport { getVersion } from \"./utils/cli.helpers\";\nimport { detectPackageManagerFromUserAgent } from \"../helpers/global.helpers\";\nimport sheu from \"../sheu\";\n\n// Constants\nconst BUILD_DIR = \".build\";\nconst MODULE_TYPES = [\"cjs\", \"esm\"] as const;\ntype ModuleType = (typeof MODULE_TYPES)[number];\n\ninterface BuildOptions {\n config?: string;\n module?: string;\n}\n\n/**\n * Main build function for the arkos CLI\n */\nexport function buildCommand(options: BuildOptions = {}) {\n const fileExt = getUserFileExtension();\n if (process.env.NODE_ENV === \"test\" || !process.env.NODE_ENV)\n process.env.NODE_ENV = \"production\";\n process.env.ARKOS_BUILD = \"true\";\n\n const envFiles = loadEnvironmentVariables();\n const moduleType = validateModuleType(options.module);\n\n try {\n console.info(` \\x1b[1m\\x1b[36m Arkos.js ${getVersion()}\\x1b[0m`);\n console.info(\n ` - Environments: ${fullCleanCwd(envFiles?.join(\", \") || \"\")\n .replaceAll(`${process.cwd()}/`, \"\")\n .replaceAll(\"/\", \"\")}`\n );\n\n console.info(`\\n Creating an optimized production build...`);\n\n ensureBuildDir();\n\n // Detect project type\n\n if (fileExt === \"ts\") {\n buildTypeScriptProject(options, moduleType);\n } else {\n buildJavaScriptProject(options, moduleType);\n }\n\n const packageManger = detectPackageManagerFromUserAgent();\n\n console.info(`\\n\\x1b[1m\\x1b[32m Build complete!\\x1b[0m\\n`);\n console.info(` \\x1b[1mNext step:\\x1b[0m`);\n console.info(\n ` Run it using \\x1b[1m\\x1b[36m${packageManger} run start\\x1b[0m\\n`\n );\n } catch (err: any) {\n console.info(\"\");\n sheu.error(`Build failed: ${err?.message}`);\n console.error(err);\n process.exit(1);\n }\n}\n\n/**\n * Validates and normalizes module type option\n */\nfunction validateModuleType(moduleType?: string): ModuleType {\n if (!moduleType) return \"cjs\";\n\n const normalizedType = moduleType.toLowerCase();\n\n // Map common terms to our module types\n if (normalizedType === \"cjs\" || normalizedType === \"commonjs\") {\n return \"cjs\";\n } else if (\n [\"esm\", \"es\", \"es2020\", \"esnext\", \"module\"].includes(normalizedType)\n ) {\n return \"esm\";\n }\n\n // Default to CJS if unrecognized\n console.warn(\n `⚠️ Unrecognized module type \"${moduleType}\", defaulting to \"cjs\"`\n );\n return \"cjs\";\n}\n\n/**\n * Ensure the build directory exists\n */\nfunction ensureBuildDir() {\n if (!fs.existsSync(BUILD_DIR)) {\n fs.mkdirSync(BUILD_DIR, { recursive: true });\n }\n\n // Create module-specific subdirectories\n for (const moduleType of MODULE_TYPES) {\n const moduleDir = path.join(BUILD_DIR, moduleType);\n if (!fs.existsSync(moduleDir)) {\n fs.mkdirSync(moduleDir, { recursive: true });\n }\n }\n}\n\n/**\n * Build a TypeScript project\n */\nfunction buildTypeScriptProject(options: BuildOptions, moduleType: ModuleType) {\n // Read the user's tsconfig.json\n const tsconfigPath = path.join(\n process.cwd(),\n options.config || \"tsconfig.json\"\n );\n let tsconfig: any = {};\n\n try {\n if (fs.existsSync(tsconfigPath)) {\n const tsconfigContent = fs.readFileSync(tsconfigPath, \"utf8\");\n tsconfig = JSON.parse(tsconfigContent);\n }\n } catch (error) {\n console.error(\"❌ Error reading tsconfig.json:\", error);\n // Continue with default config\n }\n\n // Create a custom tsconfig that outputs to our build directory with the correct module type\n const tempTsconfig = {\n ...tsconfig,\n compilerOptions: {\n ...(tsconfig.compilerOptions || {}),\n rootDir: \".\",\n outDir: path.join(`./${BUILD_DIR}`),\n // module: moduleType === \"esm\" ? \"ESNext\" : \"CommonJS\",\n },\n };\n\n const tempTsconfigPath = path.join(\n process.cwd(),\n `tsconfig.arkos-build.json`\n );\n fs.writeFileSync(tempTsconfigPath, JSON.stringify(tempTsconfig, null, 2));\n\n try {\n execSync(`npx trash ${BUILD_DIR} && npx tsc -p ${tempTsconfigPath}`, {\n stdio: \"inherit\",\n cwd: process.cwd(),\n });\n\n copyAllNonSourceFiles(moduleType, [\".ts\", \".tsx\"]);\n\n // Clean up temp config\n cleanupTempConfig(tempTsconfigPath);\n } catch (error) {\n cleanupTempConfig(tempTsconfigPath);\n throw error;\n }\n}\n\n/**\n * Build a JavaScript project\n */\nfunction buildJavaScriptProject(_: BuildOptions, moduleType: ModuleType) {\n const targetDir = path.join(BUILD_DIR);\n\n try {\n if (moduleType === \"esm\") {\n execSync(\n `npx copyfiles -u 0 \"src/**/*.js\" \"src/**/*.jsx\" \"src/**/*.mjs\" ${targetDir}`,\n {\n stdio: \"inherit\",\n cwd: process.cwd(),\n }\n );\n\n console.info(\"Note: .cjs files are skipped in ESM build\");\n } else {\n execSync(\n `npx copyfiles -u 0 \"src/**/*.js\" \"src/**/*.jsx\" \"src/**/*.cjs\" \"src/**/*.mjs\" ${targetDir}`,\n {\n stdio: \"inherit\",\n cwd: process.cwd(),\n }\n );\n }\n\n copyAllNonSourceFiles(moduleType, [\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".ts\",\n \".tsx\",\n ]);\n\n // Create appropriate package.json in the build directory\n createModulePackageJson(moduleType);\n } catch (error) {\n console.error(\"❌ Error building JavaScript project:\", error);\n throw error;\n }\n}\n\n/**\n * Copy all non-source code files to the build directory\n * This function will copy everything except the specified source file extensions\n */\nfunction copyAllNonSourceFiles(_: ModuleType, skipExtensions: string[]) {\n const targetDir = path.join(BUILD_DIR);\n const sourceDir = \"src\";\n\n try {\n // Recursive function to copy files\n function copyDirRecursive(dir: string) {\n if (!fs.existsSync(dir)) return;\n\n const items = fs.readdirSync(dir);\n\n for (const item of items) {\n const sourcePath = path.join(dir, item);\n const targetPath = path.join(\n targetDir,\n dir.replace(sourceDir, \"\"),\n item\n );\n\n // Get file stats\n const stats = fs.statSync(sourcePath);\n\n if (stats.isDirectory()) {\n // Ensure target directory exists\n if (!fs.existsSync(targetPath)) {\n fs.mkdirSync(targetPath, { recursive: true });\n }\n // Recurse into subdirectory\n copyDirRecursive(sourcePath);\n } else if (stats.isFile()) {\n // Check if this is a file we should skip\n const ext = path.extname(item).toLowerCase();\n if (!skipExtensions.includes(ext)) {\n // Ensure the target directory exists\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n // Copy the file\n fs.copyFileSync(sourcePath, targetPath);\n }\n }\n }\n }\n\n // Start copying from src directory\n copyDirRecursive(sourceDir);\n\n // Copy project root files if needed\n const rootFilesToCopy = [\"README.md\", \"LICENSE\"];\n\n for (const file of rootFilesToCopy) {\n if (fs.existsSync(path.join(process.cwd(), file))) {\n fs.copyFileSync(\n path.join(process.cwd(), file),\n path.join(targetDir, file)\n );\n }\n }\n\n // console.info(`Copied all non-source files to ${targetDir}`);\n } catch (error) {\n console.warn(\"Warning: Error copying project files:\", error);\n console.error(error);\n }\n}\n\n/**\n * Create appropriate package.json in the build directory\n */\nfunction createModulePackageJson(moduleType: ModuleType) {\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n return;\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\"));\n const buildPackageJson: any = {\n name: packageJson.name,\n version: packageJson.version,\n description: packageJson.description,\n main: \"index.js\",\n dependencies: packageJson.dependencies,\n };\n\n // Set appropriate type field for ESM\n if (moduleType === \"esm\") {\n buildPackageJson.type = \"module\";\n }\n\n const targetDir = path.join(BUILD_DIR, moduleType);\n fs.writeFileSync(\n path.join(targetDir, \"package.json\"),\n JSON.stringify(buildPackageJson, null, 2)\n );\n } catch (error) {\n console.warn(\n \"Warning: Failed to create module-specific package.json\",\n error\n );\n }\n}\n\n/**\n * Clean up temporary tsconfig\n */\nfunction cleanupTempConfig(configPath: string) {\n try {\n if (fs.existsSync(configPath)) fs.unlinkSync(configPath);\n } catch (error) {\n console.warn(\"Warning: Error cleaning up temporary config:\", error);\n }\n}\n"]}
|
|
@@ -17,6 +17,7 @@ let envFiles;
|
|
|
17
17
|
async function startCommand(options = {}) {
|
|
18
18
|
if (process.env.NODE_ENV === "test" || !process.env.NODE_ENV)
|
|
19
19
|
process.env.NODE_ENV = "production";
|
|
20
|
+
process.env.ARKOS_BUILD = "true";
|
|
20
21
|
envFiles = (0, dotenv_helpers_1.loadEnvironmentVariables)();
|
|
21
22
|
try {
|
|
22
23
|
const { port, host } = options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../src/utils/cli/start.ts"],"names":[],"mappings":";;;;;AAmBA,
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../src/utils/cli/start.ts"],"names":[],"mappings":";;;;;AAmBA,oCAsDC;AAKD,4EAGC;AAjFD,gDAAwB;AACxB,4CAAoB;AACpB,iDAAoD;AACpD,sDAA6D;AAC7D,sDAAqD;AACrD,kGAAuE;AACvE,kFAAyD;AAOzD,IAAI,KAAK,GAAwB,IAAI,CAAC;AACtC,IAAI,QAA8B,CAAC;AAK5B,KAAK,UAAU,YAAY,CAAC,UAAwB,EAAE;IAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ;QAC1D,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC;IAEjC,QAAQ,GAAG,IAAA,yCAAwB,GAAE,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;QAE/B,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEvE,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CACX,qDAAqD,IAAA,yBAAY,EAAC,UAAU,CAAC,EAAE,CAChF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,GAA4B;YACnC,QAAQ,EAAE,YAAY;YACtB,GAAG,OAAO,CAAC,GAAG;YACd,GAAG,CAAC,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YAC/B,WAAW,EAAE,MAAM;SACpB,CAAC;QAEF,KAAK,GAAG,IAAA,qBAAK,EAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE;YAClC,KAAK,EAAE,SAAS;YAChB,GAAG;YACH,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACxB,IAAI,KAAK;gBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAExB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,MAAM,iCAAoB,CAAC,uBAAuB,CACpE,GAAG,EACH;YACE,UAAU,EAAE,IAAI;SACjB,CACF,CAAC;QAEF,2BAAgB,CAAC,KAAK,CAAC;YACrB,QAAQ;YACR,GAAG,WAAW;SACf,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAKD,SAAgB,gCAAgC;IAC7C,KAAsB,EAAE,IAAI,EAAE,EAAE,CAAC;IAClC,KAAK,GAAG,IAAI,CAAC;AACf,CAAC","sourcesContent":["import path from \"path\";\nimport fs from \"fs\";\nimport { ChildProcess, spawn } from \"child_process\";\nimport { loadEnvironmentVariables } from \"../dotenv.helpers\";\nimport { fullCleanCwd } from \"../helpers/fs.helpers\";\nimport portAndHostAllocator from \"../features/port-and-host-allocator\";\nimport watermarkStamper from \"./utils/watermark-stamper\";\n\ninterface StartOptions {\n port?: string;\n host?: string;\n}\n\nlet child: ChildProcess | null = null;\nlet envFiles: string[] | undefined;\n\n/**\n * Production start command for the arkos CLI\n */\nexport async function startCommand(options: StartOptions = {}) {\n if (process.env.NODE_ENV === \"test\" || !process.env.NODE_ENV)\n process.env.NODE_ENV = \"production\";\n process.env.ARKOS_BUILD = \"true\";\n\n envFiles = loadEnvironmentVariables();\n\n try {\n const { port, host } = options;\n\n const entryPoint = path.join(process.cwd(), \".build\", \"src\", \"app.js\");\n\n if (!fs.existsSync(path.join(entryPoint))) {\n console.error(\n `❌ Could not find built application entry point at ${fullCleanCwd(entryPoint)}`\n );\n process.exit(1);\n }\n\n const env: { [x: string]: string } = {\n NODE_ENV: \"production\",\n ...process.env,\n ...(port && { CLI_PORT: port }),\n ...(host && { CLI_HOST: host }),\n ARKOS_BUILD: \"true\",\n };\n\n child = spawn(\"node\", [entryPoint], {\n stdio: \"inherit\",\n env,\n shell: true,\n });\n\n process.on(\"SIGINT\", () => {\n if (child) child.kill();\n\n process.exit(0);\n });\n\n const hostAndPort = await portAndHostAllocator.getHostAndAvailablePort(\n env,\n {\n logWarning: true,\n }\n );\n\n watermarkStamper.stamp({\n envFiles,\n ...hostAndPort,\n });\n } catch (error) {\n console.error(\"❌ Production server failed to start:\", error);\n process.exit(1);\n }\n}\n\n/**\n * Help function to help other processes to terminate the production server child process\n */\nexport function killProductionServerChildProcess() {\n (child as ChildProcess)?.kill?.();\n child = null;\n}\n"]}
|
|
@@ -20,7 +20,7 @@ function loadEnvironmentVariables() {
|
|
|
20
20
|
];
|
|
21
21
|
envFiles.forEach((filePath) => {
|
|
22
22
|
if (fs_1.default.existsSync(filePath)) {
|
|
23
|
-
if (
|
|
23
|
+
if (process.env.ARKOS_BUILD === "true" && filePath.endsWith(".local"))
|
|
24
24
|
console.info(`Skipping the local ${filePath.replace(cwd, "")} files in production`);
|
|
25
25
|
else {
|
|
26
26
|
const result = dotenv_1.default.config({ path: filePath, override: true });
|
|
@@ -36,6 +36,7 @@ function loadEnvironmentVariables() {
|
|
|
36
36
|
const missingVars = requiredVars.filter((varName) => !process.env[varName]);
|
|
37
37
|
if (missingVars.length > 0) {
|
|
38
38
|
console.error("Missing required environment variables:", missingVars.join(", "));
|
|
39
|
+
throw new Error(`Missing required environment variables: ${missingVars.join(", ")}`);
|
|
39
40
|
}
|
|
40
41
|
if (loadedEnvs)
|
|
41
42
|
return loadedEnvs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dotenv.helpers.js","sourceRoot":"","sources":["../../../src/utils/dotenv.helpers.ts"],"names":[],"mappings":";;;;;AAaA,
|
|
1
|
+
{"version":3,"file":"dotenv.helpers.js","sourceRoot":"","sources":["../../../src/utils/dotenv.helpers.ts"],"names":[],"mappings":";;;;;AAaA,4DA2CC;AAxDD,gDAAwB;AACxB,4CAAoB;AACpB,oDAA4B;AAW5B,SAAgB,wBAAwB;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,UAAU,GAAa,EAAE,CAAC;IAE9B,MAAM,QAAQ,GAAG;QACf,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC;QAClC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,EAAE,CAAC;QAChC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,QAAQ,CAAC;QACtC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC;QAC/B,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC5B,IAAI,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBACnE,OAAO,CAAC,IAAI,CACV,sBAAsB,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,sBAAsB,CACtE,CAAC;iBACC,CAAC;gBACJ,MAAM,MAAM,GAAG,gBAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAEjE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,OAAO,CAAC,IAAI,CAAC,0BAA0B,QAAQ,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACnE,CAAC;;oBAAM,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,CAAC,cAAc,CAAC,CAAC;IACtC,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAE5E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CACX,yCAAyC,EACzC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CACvB,CAAC;QACF,MAAM,IAAI,KAAK,CACb,2CAA2C,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpE,CAAC;IACJ,CAAC;IAED,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;AACpC,CAAC","sourcesContent":["import path from \"path\";\nimport fs from \"fs\";\nimport dotenv from \"dotenv\";\n\n/**\n * Loads environment variables in a prioritized order\n * 1. Base defaults (.env.defaults) - lowest priority\n * 2. Environment-specific (.env.{NODE_ENV})\n * 3. Environment-specific local (.env.{NODE_ENV}.local)\n * 4. Local environment overrides (.env.local)\n * 5. Main .env file (.env)\n * 6. Process environment variables - highest priority (already loaded by Node)\n */\nexport function loadEnvironmentVariables() {\n const ENV = process.env.NODE_ENV;\n const cwd = process.cwd();\n let loadedEnvs: string[] = [];\n\n const envFiles = [\n path.resolve(cwd, `.env.defaults`),\n path.resolve(cwd, `.env.${ENV}`),\n path.resolve(cwd, `.env.${ENV}.local`),\n path.resolve(cwd, \".env.local\"),\n path.resolve(cwd, \".env\"),\n ];\n\n envFiles.forEach((filePath) => {\n if (fs.existsSync(filePath)) {\n if (process.env.ARKOS_BUILD === \"true\" && filePath.endsWith(\".local\"))\n console.info(\n `Skipping the local ${filePath.replace(cwd, \"\")} files in production`\n );\n else {\n const result = dotenv.config({ path: filePath, override: true });\n\n if (result.error) {\n console.warn(`Warning: Error loading ${filePath}`, result.error);\n } else loadedEnvs.push(filePath);\n }\n }\n });\n\n const requiredVars = [\"DATABASE_URL\"];\n const missingVars = requiredVars.filter((varName) => !process.env[varName]);\n\n if (missingVars.length > 0) {\n console.error(\n \"Missing required environment variables:\",\n missingVars.join(\", \")\n );\n throw new Error(\n `Missing required environment variables: ${missingVars.join(\", \")}`\n );\n }\n\n if (loadedEnvs) return loadedEnvs;\n}\n"]}
|