arkos 1.3.4-canary.8 → 1.3.5-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +16 -6
  2. package/dist/cjs/exports/controllers/index.js +36 -5
  3. package/dist/cjs/exports/controllers/index.js.map +1 -1
  4. package/dist/cjs/modules/auth/auth.controller.js +22 -15
  5. package/dist/cjs/modules/auth/auth.controller.js.map +1 -1
  6. package/dist/cjs/modules/base/base.controller.js +3 -0
  7. package/dist/cjs/modules/base/base.controller.js.map +1 -1
  8. package/dist/cjs/modules/base/base.middlewares.js +70 -12
  9. package/dist/cjs/modules/base/base.middlewares.js.map +1 -1
  10. package/dist/cjs/modules/base/base.service.js +1 -2
  11. package/dist/cjs/modules/base/base.service.js.map +1 -1
  12. package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js +3 -6
  13. package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js.map +1 -1
  14. package/dist/cjs/modules/email/email.service.js +24 -27
  15. package/dist/cjs/modules/email/email.service.js.map +1 -1
  16. package/dist/cjs/modules/file-upload/file-upload.controller.js +6 -0
  17. package/dist/cjs/modules/file-upload/file-upload.controller.js.map +1 -1
  18. package/dist/cjs/types/index.js.map +1 -1
  19. package/dist/cjs/utils/cli/generate.js +1 -2
  20. package/dist/cjs/utils/cli/generate.js.map +1 -1
  21. package/dist/cjs/utils/cli/utils/cli.helpers.js +1 -1
  22. package/dist/cjs/utils/cli/utils/template-generator/templates/auth-configs-template.js +1 -1
  23. package/dist/cjs/utils/cli/utils/template-generator/templates/auth-configs-template.js.map +1 -1
  24. package/dist/cjs/utils/cli/utils/template-generator/templates/controller-template.js +30 -7
  25. package/dist/cjs/utils/cli/utils/template-generator/templates/controller-template.js.map +1 -1
  26. package/dist/cjs/utils/cli/utils/template-generator/templates/middlewares-template.js +17 -17
  27. package/dist/cjs/utils/cli/utils/template-generator/templates/middlewares-template.js.map +1 -1
  28. package/dist/cjs/utils/cli/utils/template-generator/templates/query-options-template.js +4 -6
  29. package/dist/cjs/utils/cli/utils/template-generator/templates/query-options-template.js.map +1 -1
  30. package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js +2 -4
  31. package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js.map +1 -1
  32. package/dist/cjs/utils/cli/utils/template-generator/templates/service-template.js +33 -11
  33. package/dist/cjs/utils/cli/utils/template-generator/templates/service-template.js.map +1 -1
  34. package/dist/cjs/utils/features/api.features.js +7 -7
  35. package/dist/cjs/utils/features/api.features.js.map +1 -1
  36. package/dist/esm/exports/controllers/index.js +2 -2
  37. package/dist/esm/exports/controllers/index.js.map +1 -1
  38. package/dist/esm/modules/auth/auth.controller.js +22 -15
  39. package/dist/esm/modules/auth/auth.controller.js.map +1 -1
  40. package/dist/esm/modules/base/base.controller.js +3 -0
  41. package/dist/esm/modules/base/base.controller.js.map +1 -1
  42. package/dist/esm/modules/base/base.middlewares.js +70 -11
  43. package/dist/esm/modules/base/base.middlewares.js.map +1 -1
  44. package/dist/esm/modules/base/base.service.js +1 -2
  45. package/dist/esm/modules/base/base.service.js.map +1 -1
  46. package/dist/esm/modules/base/utils/helpers/base.service.helpers.js +3 -6
  47. package/dist/esm/modules/base/utils/helpers/base.service.helpers.js.map +1 -1
  48. package/dist/esm/modules/email/email.service.js +24 -27
  49. package/dist/esm/modules/email/email.service.js.map +1 -1
  50. package/dist/esm/modules/file-upload/file-upload.controller.js +5 -1
  51. package/dist/esm/modules/file-upload/file-upload.controller.js.map +1 -1
  52. package/dist/esm/types/index.js.map +1 -1
  53. package/dist/esm/utils/cli/generate.js +1 -2
  54. package/dist/esm/utils/cli/generate.js.map +1 -1
  55. package/dist/esm/utils/cli/utils/cli.helpers.js +1 -1
  56. package/dist/esm/utils/cli/utils/template-generator/templates/auth-configs-template.js +1 -1
  57. package/dist/esm/utils/cli/utils/template-generator/templates/auth-configs-template.js.map +1 -1
  58. package/dist/esm/utils/cli/utils/template-generator/templates/controller-template.js +30 -7
  59. package/dist/esm/utils/cli/utils/template-generator/templates/controller-template.js.map +1 -1
  60. package/dist/esm/utils/cli/utils/template-generator/templates/middlewares-template.js +17 -17
  61. package/dist/esm/utils/cli/utils/template-generator/templates/middlewares-template.js.map +1 -1
  62. package/dist/esm/utils/cli/utils/template-generator/templates/query-options-template.js +4 -6
  63. package/dist/esm/utils/cli/utils/template-generator/templates/query-options-template.js.map +1 -1
  64. package/dist/esm/utils/cli/utils/template-generator/templates/router-template.js +2 -4
  65. package/dist/esm/utils/cli/utils/template-generator/templates/router-template.js.map +1 -1
  66. package/dist/esm/utils/cli/utils/template-generator/templates/service-template.js +33 -11
  67. package/dist/esm/utils/cli/utils/template-generator/templates/service-template.js.map +1 -1
  68. package/dist/esm/utils/features/api.features.js +7 -7
  69. package/dist/esm/utils/features/api.features.js.map +1 -1
  70. package/dist/types/exports/controllers/index.d.ts +2 -2
  71. package/dist/types/modules/base/base.middlewares.d.ts +0 -1
  72. package/dist/types/modules/file-upload/file-upload.controller.d.ts +1 -1
  73. package/dist/types/types/index.d.ts +13 -9
  74. package/package.json +1 -1
@@ -4,21 +4,43 @@ export function generateServiceTemplate(options) {
4
4
  const ext = getUserFileExtension();
5
5
  const isTypeScript = ext === "ts";
6
6
  if (!modelName)
7
- throw new Error("Model name is required for service template");
8
- const prismaImport = isTypeScript
9
- ? `"../../utils/prisma${ext === "ts" ? "" : "." + "js"}";\n`
7
+ throw new Error("Module name is required for service template");
8
+ const camelName = modelName.camel.toLowerCase();
9
+ let serviceType;
10
+ let serviceName;
11
+ let serviceImport;
12
+ if (camelName === "fileupload") {
13
+ serviceType = "fileUpload";
14
+ serviceName = "FileUploadService";
15
+ serviceImport = imports?.fileUploadService || "arkos/services";
16
+ }
17
+ else if (camelName === "auth") {
18
+ serviceType = "auth";
19
+ serviceName = "AuthService";
20
+ serviceImport = imports?.authService || "arkos/services";
21
+ }
22
+ else if (camelName === "email") {
23
+ serviceType = "email";
24
+ serviceName = "EmailService";
25
+ serviceImport = imports?.emailService || "arkos/services";
26
+ }
27
+ else {
28
+ serviceType = "base";
29
+ serviceName = "BaseService";
30
+ serviceImport = imports?.baseService || "arkos/services";
31
+ }
32
+ const prismaImport = isTypeScript && serviceType === "base"
33
+ ? `import { Prisma } from "@prisma/client";\n`
10
34
  : "";
11
- const baseServiceImport = isTypeScript
12
- ? `import { BaseService } from "${imports?.baseService || "arkos/services"}";`
13
- : `import { BaseService } from "${imports?.baseService || "arkos/services"}";`;
14
- const typeParameter = isTypeScript
15
- ? `<typeof prisma.${modelName.camel}>`
35
+ const serviceClassImport = `import { ${serviceName} } from "${serviceImport}";`;
36
+ const typeParameter = isTypeScript && serviceType === "base"
37
+ ? `<Prisma.${modelName.pascal}Delegate>`
16
38
  : "";
17
- return `${isTypeScript && "import prisma from "}${prismaImport}${baseServiceImport}
39
+ return `${prismaImport}${serviceClassImport}
18
40
 
19
- class ${modelName.pascal}Service extends BaseService${typeParameter} {}
41
+ class ${modelName.pascal}Service extends ${serviceName}${typeParameter} {}
20
42
 
21
- const ${modelName.camel}Service = new ${modelName.pascal}Service("${modelName.kebab}");
43
+ const ${modelName.camel}Service = new ${modelName.pascal}Service(${serviceType === "base" ? `"${modelName.kebab}"` : ""});
22
44
 
23
45
  export default ${modelName.camel}Service;
24
46
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"service-template.js","sourceRoot":"","sources":["../../../../../../../src/utils/cli/utils/template-generator/templates/service-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAGtE,MAAM,UAAU,uBAAuB,CAAC,OAAwB;IAC9D,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACvC,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,GAAG,KAAK,IAAI,CAAC;IAElC,IAAI,CAAC,SAAS;QACZ,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAGjE,MAAM,YAAY,GAAG,YAAY;QAC/B,CAAC,CAAC,sBAAsB,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,MAAM;QAC5D,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,iBAAiB,GAAG,YAAY;QACpC,CAAC,CAAC,gCACE,OAAO,EAAE,WAAW,IAAI,gBAC1B,IAAI;QACN,CAAC,CAAC,gCACE,OAAO,EAAE,WAAW,IAAI,gBAC1B,IAAI,CAAC;IAGT,MAAM,aAAa,GAAG,YAAY;QAChC,CAAC,CAAC,kBAAkB,SAAS,CAAC,KAAK,GAAG;QACtC,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,GAAG,YAAY,IAAI,qBAAqB,GAAG,YAAY,GAAG,iBAAiB;;QAE5E,SAAS,CAAC,MAAM,8BAA8B,aAAa;;QAE3D,SAAS,CAAC,KAAK,iBAAiB,SAAS,CAAC,MAAM,YAAY,SAAS,CAAC,KAAK;;iBAElE,SAAS,CAAC,KAAK;CAC/B,CAAC;AACF,CAAC","sourcesContent":["import { getUserFileExtension } from \"../../../../helpers/fs.helpers\";\nimport { TemplateOptions } from \"../../template-generators\";\n\nexport function generateServiceTemplate(options: TemplateOptions): string {\n const { modelName, imports } = options;\n const ext = getUserFileExtension();\n const isTypeScript = ext === \"ts\";\n\n if (!modelName)\n throw new Error(\"Model name is required for service template\");\n\n // Generate imports\n const prismaImport = isTypeScript\n ? `\"../../utils/prisma${ext === \"ts\" ? \"\" : \".\" + \"js\"}\";\\n`\n : \"\";\n\n const baseServiceImport = isTypeScript\n ? `import { BaseService } from \"${\n imports?.baseService || \"arkos/services\"\n }\";`\n : `import { BaseService } from \"${\n imports?.baseService || \"arkos/services\"\n }\";`;\n\n // Generate type parameter for TypeScript\n const typeParameter = isTypeScript\n ? `<typeof prisma.${modelName.camel}>`\n : \"\";\n\n return `${isTypeScript && \"import prisma from \"}${prismaImport}${baseServiceImport}\n \nclass ${modelName.pascal}Service extends BaseService${typeParameter} {}\n\nconst ${modelName.camel}Service = new ${modelName.pascal}Service(\"${modelName.kebab}\");\n\nexport default ${modelName.camel}Service;\n`;\n}\n"]}
1
+ {"version":3,"file":"service-template.js","sourceRoot":"","sources":["../../../../../../../src/utils/cli/utils/template-generator/templates/service-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAGtE,MAAM,UAAU,uBAAuB,CAAC,OAAwB;IAC9D,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACvC,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,GAAG,KAAK,IAAI,CAAC;IAElC,IAAI,CAAC,SAAS;QACZ,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAElE,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IAChD,IAAI,WAAqD,CAAC;IAC1D,IAAI,WAAmB,CAAC;IACxB,IAAI,aAAqB,CAAC;IAE1B,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;QAC/B,WAAW,GAAG,YAAY,CAAC;QAC3B,WAAW,GAAG,mBAAmB,CAAC;QAClC,aAAa,GAAG,OAAO,EAAE,iBAAiB,IAAI,gBAAgB,CAAC;IACjE,CAAC;SAAM,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,WAAW,GAAG,MAAM,CAAC;QACrB,WAAW,GAAG,aAAa,CAAC;QAC5B,aAAa,GAAG,OAAO,EAAE,WAAW,IAAI,gBAAgB,CAAC;IAC3D,CAAC;SAAM,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QACjC,WAAW,GAAG,OAAO,CAAC;QACtB,WAAW,GAAG,cAAc,CAAC;QAC7B,aAAa,GAAG,OAAO,EAAE,YAAY,IAAI,gBAAgB,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,MAAM,CAAC;QACrB,WAAW,GAAG,aAAa,CAAC;QAC5B,aAAa,GAAG,OAAO,EAAE,WAAW,IAAI,gBAAgB,CAAC;IAC3D,CAAC;IAED,MAAM,YAAY,GAChB,YAAY,IAAI,WAAW,KAAK,MAAM;QACpC,CAAC,CAAC,4CAA4C;QAC9C,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,kBAAkB,GAAG,YAAY,WAAW,YAAY,aAAa,IAAI,CAAC;IAEhF,MAAM,aAAa,GACjB,YAAY,IAAI,WAAW,KAAK,MAAM;QACpC,CAAC,CAAC,WAAW,SAAS,CAAC,MAAM,WAAW;QACxC,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,GAAG,YAAY,GAAG,kBAAkB;;QAErC,SAAS,CAAC,MAAM,mBAAmB,WAAW,GAAG,aAAa;;QAE9D,SAAS,CAAC,KAAK,iBAAiB,SAAS,CAAC,MAAM,WAAW,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE;;iBAEtG,SAAS,CAAC,KAAK;CAC/B,CAAC;AACF,CAAC","sourcesContent":["import { getUserFileExtension } from \"../../../../helpers/fs.helpers\";\nimport { TemplateOptions } from \"../../template-generators\";\n\nexport function generateServiceTemplate(options: TemplateOptions): string {\n const { modelName, imports } = options;\n const ext = getUserFileExtension();\n const isTypeScript = ext === \"ts\";\n\n if (!modelName)\n throw new Error(\"Module name is required for service template\");\n\n const camelName = modelName.camel.toLowerCase();\n let serviceType: \"fileUpload\" | \"auth\" | \"email\" | \"base\";\n let serviceName: string;\n let serviceImport: string;\n\n if (camelName === \"fileupload\") {\n serviceType = \"fileUpload\";\n serviceName = \"FileUploadService\";\n serviceImport = imports?.fileUploadService || \"arkos/services\";\n } else if (camelName === \"auth\") {\n serviceType = \"auth\";\n serviceName = \"AuthService\";\n serviceImport = imports?.authService || \"arkos/services\";\n } else if (camelName === \"email\") {\n serviceType = \"email\";\n serviceName = \"EmailService\";\n serviceImport = imports?.emailService || \"arkos/services\";\n } else {\n serviceType = \"base\";\n serviceName = \"BaseService\";\n serviceImport = imports?.baseService || \"arkos/services\";\n }\n\n const prismaImport =\n isTypeScript && serviceType === \"base\"\n ? `import { Prisma } from \"@prisma/client\";\\n`\n : \"\";\n\n const serviceClassImport = `import { ${serviceName} } from \"${serviceImport}\";`;\n\n const typeParameter =\n isTypeScript && serviceType === \"base\"\n ? `<Prisma.${modelName.pascal}Delegate>`\n : \"\";\n\n return `${prismaImport}${serviceClassImport}\n \nclass ${modelName.pascal}Service extends ${serviceName}${typeParameter} {}\n\nconst ${modelName.camel}Service = new ${modelName.pascal}Service(${serviceType === \"base\" ? `\"${modelName.kebab}\"` : \"\"});\n\nexport default ${modelName.camel}Service;\n`;\n}\n"]}
@@ -179,27 +179,27 @@ export default class APIFeatures {
179
179
  return this;
180
180
  }
181
181
  _validateNoPasswordExposure(select, include, omit) {
182
- const checkForPassword = (obj, path = []) => {
182
+ const checkForPassword = (obj, prismaKey, path = []) => {
183
183
  for (const [key, value] of Object.entries(obj)) {
184
184
  const currentPath = [...path, key];
185
185
  if (key === "password" &&
186
186
  (this.modelName?.toLowerCase() === "user" ||
187
187
  currentPath.at(-3)?.toLowerCase?.() === "user")) {
188
- if (value === false)
188
+ if (value === false && prismaKey === "omit")
189
189
  throw new AppError("Cannot disable password omission protection", 400, { ...obj }, "CannotExposeUserPassword");
190
- if (value === true && !omit?.["password"])
190
+ if (value === true && ["include", "select"].includes(prismaKey))
191
191
  throw new AppError("User password exposure detected", 403, {}, "UserPasswordExposureDetected");
192
192
  }
193
193
  if (typeof value === "object" &&
194
194
  value !== null &&
195
195
  !Array.isArray(value)) {
196
- checkForPassword(value, currentPath);
196
+ checkForPassword(value, prismaKey, currentPath);
197
197
  }
198
198
  }
199
199
  };
200
- checkForPassword(select);
201
- checkForPassword(include);
202
- checkForPassword(omit);
200
+ checkForPassword(select, "select");
201
+ checkForPassword(include, "include");
202
+ checkForPassword(omit, "omit");
203
203
  }
204
204
  paginate() {
205
205
  const paginationOptions = (() => {
@@ -1 +1 @@
1
- {"version":3,"file":"api.features.js","sourceRoot":"","sources":["../../../../src/utils/features/api.features.ts"],"names":[],"mappings":"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","sourcesContent":["import { Request } from \"express\";\nimport deepmerge from \"../helpers/deepmerge.helper\";\nimport { parseQueryParamsWithModifiers } from \"../helpers/api.features.helpers\";\nimport AppError from \"../../modules/error-handler/utils/app-error\";\nimport { getPrismaInstance } from \"../helpers/prisma.helpers\";\nimport { ArkosRequest } from \"../../types\";\nimport debuggerService from \"../../modules/debugger/debugger.service\";\n\ntype ModelName = string;\n\nexport default class APIFeatures {\n req?: ArkosRequest;\n searchParams: any;\n searchParamsWithModifiers: any;\n filters: Record<string, any> = {};\n reqFiltersSearchParam: any = {};\n modelName?: ModelName;\n excludedFields = [\n \"page\",\n \"filters\",\n \"sort\",\n \"limit\",\n \"fields\",\n \"addFields\",\n \"removeFields\",\n \"search\",\n \"include\",\n \"filterMode\",\n \"where\",\n \"prismaQueryOptions\",\n \"ignoredFields\",\n \"select\",\n \"omit\",\n ];\n\n constructor(req?: Request, modelName?: ModelName) {\n if (req) {\n const { filters = \"{}\", ...restOfQuery } = req.query;\n this.req = req;\n\n let parsedFilters = {};\n try {\n parsedFilters = JSON.parse(filters as string);\n } catch (error) {\n throw new AppError(\"Invalid req.query.filters JSON format\", 400);\n }\n\n this.searchParams = deepmerge(\n parseQueryParamsWithModifiers(restOfQuery),\n parseQueryParamsWithModifiers(parsedFilters)\n );\n\n debuggerService.handleTransformedQueryLog(this.searchParams);\n }\n\n if (modelName) this.modelName = modelName;\n this.filters = { ...this.filters };\n }\n\n filter() {\n if (!this.req)\n throw new Error(\n \"Trying to use APIFeatures.filter() without passing request on class constructor or APIFeatures.setup() method.\"\n );\n\n const searchableFields: Record<string, any>[] = [];\n const queryObj = { ...this.searchParams };\n\n this.excludedFields.forEach((el) => delete queryObj[el]);\n\n const topLevelOR = queryObj.OR;\n const topLevelAND = queryObj.AND;\n delete queryObj.OR;\n delete queryObj.AND;\n\n const whereObj = { ...this.req.params, ...queryObj };\n const whereLogicalOperatorFilters = Object.keys(whereObj).map((key) => ({\n [key]: whereObj[key],\n }));\n\n let whereOptions: any = {};\n\n if (whereLogicalOperatorFilters.length > 0) {\n whereOptions = {\n [(this.req.query?.filterMode as string) ?? \"OR\"]:\n whereLogicalOperatorFilters,\n };\n }\n\n if (topLevelOR) {\n if (whereOptions.OR) {\n whereOptions.OR = [...whereOptions.OR, ...topLevelOR];\n } else {\n whereOptions.OR = topLevelOR;\n }\n }\n\n if (topLevelAND) {\n if (whereOptions.AND) {\n whereOptions.AND = [...whereOptions.AND, ...topLevelAND];\n } else {\n whereOptions.AND = topLevelAND;\n }\n }\n\n if (!!this.searchParams.search) {\n const prisma = getPrismaInstance();\n\n if (!this.modelName)\n throw new Error(\"Model name is required for search functionality\");\n\n if (!prisma[this.modelName] || !prisma[this.modelName].fields)\n throw new Error(`Model '${this.modelName}' not found or has no fields`);\n\n Object.keys((prisma as any)[this.modelName].fields).forEach((key) => {\n const field = ((prisma as any)[this.modelName!].fields as any)[key];\n if (\n field?.typeName === \"String\" &&\n key !== \"id\" &&\n key !== \"password\" &&\n !field.isList &&\n !key?.includes?.(\"Id\") &&\n !key?.includes?.(\"ID\")\n ) {\n searchableFields.push({\n [`${key}`]: {\n contains: this.searchParams.search,\n mode: \"insensitive\",\n },\n });\n }\n });\n\n if (searchableFields.length > 0) {\n whereOptions = deepmerge(\n {\n OR: searchableFields,\n },\n whereOptions\n );\n }\n }\n\n const firstMerge = deepmerge(\n {\n where: whereOptions,\n },\n this.req.prismaQueryOptions || {}\n );\n\n this.filters = deepmerge(firstMerge, this.filters);\n this.searchParams = deepmerge(\n this.searchParams || {},\n this.req.prismaQueryOptions || {}\n );\n\n return this;\n }\n\n sort() {\n if (this.searchParams.sort) {\n const sortBy = this.searchParams?.sort\n ?.split(\",\")\n ?.map((field: string) => ({\n [field.startsWith(\"-\") ? field.substring(1) : field]:\n field.startsWith(\"-\") ? \"desc\" : \"asc\",\n }));\n this.filters = deepmerge(this.filters, { orderBy: sortBy });\n }\n\n return this;\n }\n\n limitFields() {\n let finalSelect: Record<string, any> = {};\n let finalInclude: Record<string, any> = {};\n let finalOmit: Record<string, any> = {};\n\n if (this.searchParams?.fields) {\n const fields = this.searchParams.fields.split(\",\");\n\n const regularFields = fields.filter(\n (field: string) => !field.startsWith(\"+\") && !field.startsWith(\"-\")\n );\n const includeFields = fields\n .filter((field: string) => field.startsWith(\"+\"))\n .map((field: string) => field.substring(1));\n const excludeFields = fields\n .filter((field: string) => field.startsWith(\"-\"))\n .map((field: string) => field.substring(1));\n\n if (regularFields.length > 0) {\n finalSelect = regularFields.reduce(\n (acc: Record<string, any>, field: string) => {\n acc[field] = true;\n return acc;\n },\n {} as Record<string, any>\n );\n }\n\n includeFields.forEach((field: string) => {\n finalInclude[field] = true;\n });\n\n excludeFields.forEach((field: string) => {\n finalOmit[field] = true;\n });\n }\n\n if (this.searchParams.include || this.filters.include)\n finalInclude = deepmerge(\n finalInclude,\n deepmerge(this.filters?.include || {}, this.searchParams?.include || {})\n );\n\n if (this.searchParams.select || this.filters.include)\n finalSelect = deepmerge(\n finalSelect,\n deepmerge(this.filters?.select || {}, this.searchParams?.select || {})\n );\n\n if (this.searchParams.omit || this.filters.omit)\n finalOmit = deepmerge(\n finalOmit,\n deepmerge(this.filters?.omit || {}, this.searchParams?.omit || {})\n );\n\n if (\n Object.keys(finalSelect).length > 0 &&\n Object.keys(finalInclude).length > 0\n ) {\n finalSelect = deepmerge(finalSelect, finalInclude);\n finalInclude = {};\n delete this.filters.include;\n delete this.searchParams.include;\n }\n\n this._validateNoPasswordExposure(finalSelect, finalInclude, finalOmit);\n\n // ALWAYS protect password field in finalOmit\n if (finalOmit.password === false)\n throw new AppError(\"Cannot disable password omission protection\", 400);\n\n if (this.modelName?.toLowerCase?.() === \"user\") finalOmit.password = true;\n\n if (Object.keys(finalSelect).length > 0) this.filters.select = finalSelect;\n\n if (Object.keys(finalInclude).length > 0)\n this.filters.include = finalInclude;\n\n if (Object.keys(finalOmit).length > 0) this.filters.omit = finalOmit;\n\n if (this.searchParams?.addFields || this.searchParams?.removeFields) {\n throw new AppError(\n \"The addFields and removeFields parameters are deprecated.\",\n 400\n );\n }\n\n return this;\n }\n\n private _validateNoPasswordExposure(\n select: Record<string, any>,\n include: Record<string, any>,\n omit: Record<string, any>\n ) {\n const checkForPassword = (\n obj: Record<string, any>,\n path: string[] = []\n ) => {\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (\n key === \"password\" &&\n (this.modelName?.toLowerCase() === \"user\" ||\n currentPath.at(-3)?.toLowerCase?.() === \"user\")\n ) {\n if (value === false)\n throw new AppError(\n \"Cannot disable password omission protection\",\n 400,\n { ...obj },\n \"CannotExposeUserPassword\"\n );\n\n if (value === true && !omit?.[\"password\"])\n throw new AppError(\n \"User password exposure detected\",\n 403,\n {},\n \"UserPasswordExposureDetected\"\n );\n }\n\n if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value)\n ) {\n checkForPassword(value, currentPath);\n }\n }\n };\n\n checkForPassword(select);\n checkForPassword(include);\n checkForPassword(omit);\n }\n\n paginate(): APIFeatures {\n const paginationOptions = (() => {\n if (this.searchParams.limit === \"all\") return {};\n\n const page = parseInt(this.searchParams.page, 10) || 1;\n const limit = parseInt(this.searchParams.limit, 10) || 30;\n const skip = (page - 1) * limit;\n\n return { skip, take: limit };\n })();\n\n this.filters = {\n ...this.filters,\n ...paginationOptions,\n };\n return this;\n }\n}\n"]}
1
+ {"version":3,"file":"api.features.js","sourceRoot":"","sources":["../../../../src/utils/features/api.features.ts"],"names":[],"mappings":"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","sourcesContent":["import { Request } from \"express\";\nimport deepmerge from \"../helpers/deepmerge.helper\";\nimport { parseQueryParamsWithModifiers } from \"../helpers/api.features.helpers\";\nimport AppError from \"../../modules/error-handler/utils/app-error\";\nimport { getPrismaInstance } from \"../helpers/prisma.helpers\";\nimport { ArkosRequest } from \"../../types\";\nimport debuggerService from \"../../modules/debugger/debugger.service\";\n\ntype ModelName = string;\n\nexport default class APIFeatures {\n req?: ArkosRequest;\n searchParams: any;\n searchParamsWithModifiers: any;\n filters: Record<string, any> = {};\n reqFiltersSearchParam: any = {};\n modelName?: ModelName;\n excludedFields = [\n \"page\",\n \"filters\",\n \"sort\",\n \"limit\",\n \"fields\",\n \"addFields\",\n \"removeFields\",\n \"search\",\n \"include\",\n \"filterMode\",\n \"where\",\n \"prismaQueryOptions\",\n \"ignoredFields\",\n \"select\",\n \"omit\",\n ];\n\n constructor(req?: Request, modelName?: ModelName) {\n if (req) {\n const { filters = \"{}\", ...restOfQuery } = req.query;\n this.req = req;\n\n let parsedFilters = {};\n try {\n parsedFilters = JSON.parse(filters as string);\n } catch (error) {\n throw new AppError(\"Invalid req.query.filters JSON format\", 400);\n }\n\n this.searchParams = deepmerge(\n parseQueryParamsWithModifiers(restOfQuery),\n parseQueryParamsWithModifiers(parsedFilters)\n );\n\n debuggerService.handleTransformedQueryLog(this.searchParams);\n }\n\n if (modelName) this.modelName = modelName;\n this.filters = { ...this.filters };\n }\n\n filter() {\n if (!this.req)\n throw new Error(\n \"Trying to use APIFeatures.filter() without passing request on class constructor or APIFeatures.setup() method.\"\n );\n\n const searchableFields: Record<string, any>[] = [];\n const queryObj = { ...this.searchParams };\n\n this.excludedFields.forEach((el) => delete queryObj[el]);\n\n const topLevelOR = queryObj.OR;\n const topLevelAND = queryObj.AND;\n delete queryObj.OR;\n delete queryObj.AND;\n\n const whereObj = { ...this.req.params, ...queryObj };\n const whereLogicalOperatorFilters = Object.keys(whereObj).map((key) => ({\n [key]: whereObj[key],\n }));\n\n let whereOptions: any = {};\n\n if (whereLogicalOperatorFilters.length > 0) {\n whereOptions = {\n [(this.req.query?.filterMode as string) ?? \"OR\"]:\n whereLogicalOperatorFilters,\n };\n }\n\n if (topLevelOR) {\n if (whereOptions.OR) {\n whereOptions.OR = [...whereOptions.OR, ...topLevelOR];\n } else {\n whereOptions.OR = topLevelOR;\n }\n }\n\n if (topLevelAND) {\n if (whereOptions.AND) {\n whereOptions.AND = [...whereOptions.AND, ...topLevelAND];\n } else {\n whereOptions.AND = topLevelAND;\n }\n }\n\n if (!!this.searchParams.search) {\n const prisma = getPrismaInstance();\n\n if (!this.modelName)\n throw new Error(\"Model name is required for search functionality\");\n\n if (!prisma[this.modelName] || !prisma[this.modelName].fields)\n throw new Error(`Model '${this.modelName}' not found or has no fields`);\n\n Object.keys((prisma as any)[this.modelName].fields).forEach((key) => {\n const field = ((prisma as any)[this.modelName!].fields as any)[key];\n if (\n field?.typeName === \"String\" &&\n key !== \"id\" &&\n key !== \"password\" &&\n !field.isList &&\n !key?.includes?.(\"Id\") &&\n !key?.includes?.(\"ID\")\n ) {\n searchableFields.push({\n [`${key}`]: {\n contains: this.searchParams.search,\n mode: \"insensitive\",\n },\n });\n }\n });\n\n if (searchableFields.length > 0) {\n whereOptions = deepmerge(\n {\n OR: searchableFields,\n },\n whereOptions\n );\n }\n }\n\n const firstMerge = deepmerge(\n {\n where: whereOptions,\n },\n this.req.prismaQueryOptions || {}\n );\n\n this.filters = deepmerge(firstMerge, this.filters);\n this.searchParams = deepmerge(\n this.searchParams || {},\n this.req.prismaQueryOptions || {}\n );\n\n return this;\n }\n\n sort() {\n if (this.searchParams.sort) {\n const sortBy = this.searchParams?.sort\n ?.split(\",\")\n ?.map((field: string) => ({\n [field.startsWith(\"-\") ? field.substring(1) : field]:\n field.startsWith(\"-\") ? \"desc\" : \"asc\",\n }));\n this.filters = deepmerge(this.filters, { orderBy: sortBy });\n }\n\n return this;\n }\n\n limitFields() {\n let finalSelect: Record<string, any> = {};\n let finalInclude: Record<string, any> = {};\n let finalOmit: Record<string, any> = {};\n\n if (this.searchParams?.fields) {\n const fields = this.searchParams.fields.split(\",\");\n\n const regularFields = fields.filter(\n (field: string) => !field.startsWith(\"+\") && !field.startsWith(\"-\")\n );\n const includeFields = fields\n .filter((field: string) => field.startsWith(\"+\"))\n .map((field: string) => field.substring(1));\n const excludeFields = fields\n .filter((field: string) => field.startsWith(\"-\"))\n .map((field: string) => field.substring(1));\n\n if (regularFields.length > 0) {\n finalSelect = regularFields.reduce(\n (acc: Record<string, any>, field: string) => {\n acc[field] = true;\n return acc;\n },\n {} as Record<string, any>\n );\n }\n\n includeFields.forEach((field: string) => {\n finalInclude[field] = true;\n });\n\n excludeFields.forEach((field: string) => {\n finalOmit[field] = true;\n });\n }\n\n if (this.searchParams.include || this.filters.include)\n finalInclude = deepmerge(\n finalInclude,\n deepmerge(this.filters?.include || {}, this.searchParams?.include || {})\n );\n\n if (this.searchParams.select || this.filters.include)\n finalSelect = deepmerge(\n finalSelect,\n deepmerge(this.filters?.select || {}, this.searchParams?.select || {})\n );\n\n if (this.searchParams.omit || this.filters.omit)\n finalOmit = deepmerge(\n finalOmit,\n deepmerge(this.filters?.omit || {}, this.searchParams?.omit || {})\n );\n\n if (\n Object.keys(finalSelect).length > 0 &&\n Object.keys(finalInclude).length > 0\n ) {\n finalSelect = deepmerge(finalSelect, finalInclude);\n finalInclude = {};\n delete this.filters.include;\n delete this.searchParams.include;\n }\n\n this._validateNoPasswordExposure(finalSelect, finalInclude, finalOmit);\n\n // ALWAYS protect password field in finalOmit\n if (finalOmit.password === false)\n throw new AppError(\"Cannot disable password omission protection\", 400);\n\n if (this.modelName?.toLowerCase?.() === \"user\") finalOmit.password = true;\n\n if (Object.keys(finalSelect).length > 0) this.filters.select = finalSelect;\n\n if (Object.keys(finalInclude).length > 0)\n this.filters.include = finalInclude;\n\n if (Object.keys(finalOmit).length > 0) this.filters.omit = finalOmit;\n\n if (this.searchParams?.addFields || this.searchParams?.removeFields) {\n throw new AppError(\n \"The addFields and removeFields parameters are deprecated.\",\n 400\n );\n }\n\n return this;\n }\n\n private _validateNoPasswordExposure(\n select: Record<string, any>,\n include: Record<string, any>,\n omit: Record<string, any>\n ) {\n const checkForPassword = (\n obj: Record<string, any>,\n prismaKey: string,\n path: string[] = []\n ) => {\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (\n key === \"password\" &&\n (this.modelName?.toLowerCase() === \"user\" ||\n currentPath.at(-3)?.toLowerCase?.() === \"user\")\n ) {\n if (value === false && prismaKey === \"omit\")\n throw new AppError(\n \"Cannot disable password omission protection\",\n 400,\n { ...obj },\n \"CannotExposeUserPassword\"\n );\n\n if (value === true && [\"include\", \"select\"].includes(prismaKey))\n throw new AppError(\n \"User password exposure detected\",\n 403,\n {},\n \"UserPasswordExposureDetected\"\n );\n }\n\n if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value)\n ) {\n checkForPassword(value, prismaKey, currentPath);\n }\n }\n };\n\n checkForPassword(select, \"select\");\n checkForPassword(include, \"include\");\n checkForPassword(omit, \"omit\");\n }\n\n paginate(): APIFeatures {\n const paginationOptions = (() => {\n if (this.searchParams.limit === \"all\") return {};\n\n const page = parseInt(this.searchParams.page, 10) || 1;\n const limit = parseInt(this.searchParams.limit, 10) || 30;\n const skip = (page - 1) * limit;\n\n return { skip, take: limit };\n })();\n\n this.filters = {\n ...this.filters,\n ...paginationOptions,\n };\n return this;\n }\n}\n"]}
@@ -1,3 +1,3 @@
1
1
  import { BaseController } from "./../../modules/base/base.controller";
2
- import fileUploadController from "../../modules/file-upload/file-upload.controller";
3
- export { fileUploadController, BaseController };
2
+ import fileUploadController, { FileUploadController } from "../../modules/file-upload/file-upload.controller";
3
+ export { fileUploadController, FileUploadController, BaseController };
@@ -5,7 +5,6 @@ import { ClassConstructor } from "class-transformer";
5
5
  import { ValidatorOptions } from "class-validator";
6
6
  export declare function callNext(_: Request, _1: Response, next: NextFunction): void;
7
7
  export declare function sendResponse(req: ArkosRequest, res: ArkosResponse): void;
8
- export declare function addRouteMiddlwaresAndConfigs(): void;
9
8
  export type ControllerActions = keyof PrismaQueryOptions<any> | keyof Omit<AuthPrismaQueryOptions<any>, keyof PrismaQueryOptions<any>>;
10
9
  export declare function addPrismaQueryOptionsToRequest<T extends Record<string, any>>(prismaQueryOptions: PrismaQueryOptions<T> | AuthPrismaQueryOptions<T>, action: ControllerActions): (req: ArkosRequest, _: ArkosResponse, next: NextFunction) => void;
11
10
  export declare function handleRequestLogs(req: Request, res: Response, next: NextFunction): void;
@@ -1,4 +1,4 @@
1
- declare class FileUploadController {
1
+ export declare class FileUploadController {
2
2
  private interceptors;
3
3
  uploadFile: any;
4
4
  deleteFile: any;
@@ -1,6 +1,16 @@
1
1
  import { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response } from "express";
2
2
  export type PrismaOperations = "findMany";
3
- export type PrismaQueryOptions<T extends Record<string, any>> = {
3
+ export type AuthPrismaQueryOptions<T extends Record<string, any>> = {
4
+ getMe?: Partial<Parameters<T["findUnique"]>[0]>;
5
+ updateMe?: Partial<Parameters<T["update"]>[0]>;
6
+ deleteMe?: Partial<Parameters<T["update"]>[0]>;
7
+ login?: Partial<Parameters<T["findFirst"]>[0]>;
8
+ signup?: Partial<Parameters<T["create"]>[0]>;
9
+ updatePassword?: Partial<Parameters<T["update"]>[0]>;
10
+ findManyAuthAction?: Partial<Parameters<T["findMany"]>[0]>;
11
+ findOneAuthAction?: Partial<Parameters<T["findFirst"]>[0]>;
12
+ };
13
+ type BasePrismaQueryOptions<T extends Record<string, any>> = {
4
14
  queryOptions?: Partial<Parameters<T["findMany"]>[0]>;
5
15
  global?: Partial<Parameters<T["findMany"]>[0]>;
6
16
  find?: Partial<Parameters<T["findMany"]>[0]>;
@@ -19,14 +29,7 @@ export type PrismaQueryOptions<T extends Record<string, any>> = {
19
29
  deleteOne?: Partial<Parameters<T["delete"]>[0]>;
20
30
  deleteMany?: Partial<Parameters<T["deleteMany"]>[0]>;
21
31
  };
22
- export type AuthPrismaQueryOptions<T extends Record<string, any>> = {
23
- getMe?: Partial<Parameters<T["findUnique"]>[0]>;
24
- updateMe?: Partial<Parameters<T["update"]>[0]>;
25
- deleteMe?: Partial<Parameters<T["update"]>[0]>;
26
- login?: Partial<Parameters<T["findFirst"]>[0]>;
27
- signup?: Partial<Parameters<T["create"]>[0]>;
28
- updatePassword?: Partial<Parameters<T["update"]>[0]>;
29
- };
32
+ export type PrismaQueryOptions<T extends Record<string, any>, ModelName extends string = string> = ModelName extends "auth" ? AuthPrismaQueryOptions<T> : BasePrismaQueryOptions<T>;
30
33
  export type PrismaModelDelegate = {
31
34
  create: (args: {
32
35
  data: never;
@@ -135,3 +138,4 @@ export interface ArkosRequestHandler extends RequestHandler {
135
138
  }
136
139
  export interface ArkosErrorRequestHandler extends ErrorRequestHandler {
137
140
  }
141
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkos",
3
- "version": "1.3.4-canary.8",
3
+ "version": "1.3.5-beta",
4
4
  "description": "The Express & Prisma RESTful Framework",
5
5
  "main": "dist/cjs/exports/index.js",
6
6
  "module": "dist/esm/exports/index.js",