arkos 2.0.0-next.28 → 2.0.0-next.29

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 (48) hide show
  1. package/dist/esm/app.js +27 -28
  2. package/dist/esm/app.js.map +1 -1
  3. package/dist/esm/components/arkos-route-hook/index.js +22 -18
  4. package/dist/esm/components/arkos-route-hook/index.js.map +1 -1
  5. package/dist/esm/modules/auth/auth.service.js +51 -51
  6. package/dist/esm/modules/auth/auth.service.js.map +1 -1
  7. package/dist/esm/modules/base/base.controller.js +84 -83
  8. package/dist/esm/modules/base/base.controller.js.map +1 -1
  9. package/dist/esm/modules/base/base.middlewares.js +44 -44
  10. package/dist/esm/modules/base/base.middlewares.js.map +1 -1
  11. package/dist/esm/modules/base/base.service.js +59 -59
  12. package/dist/esm/modules/base/base.service.js.map +1 -1
  13. package/dist/esm/modules/base/utils/error-prettifier.js.map +1 -1
  14. package/dist/esm/modules/swagger/utils/helpers/openapi-schema-converter.js +42 -40
  15. package/dist/esm/modules/swagger/utils/helpers/openapi-schema-converter.js.map +1 -1
  16. package/dist/esm/types/arkos-prisma-input.js.map +1 -1
  17. package/dist/esm/types/new-arkos-config.js.map +1 -1
  18. package/dist/esm/types/router-config.js.map +1 -1
  19. package/dist/esm/utils/arkos-router/index.js +37 -35
  20. package/dist/esm/utils/arkos-router/index.js.map +1 -1
  21. package/dist/esm/utils/arkos-router/types/index.js.map +1 -1
  22. package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +1 -1
  23. package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -1
  24. package/dist/esm/utils/cli/index.js +2 -2
  25. package/dist/esm/utils/cli/index.js.map +1 -1
  26. package/dist/esm/utils/cli/utils/cli.helpers.js +1 -1
  27. package/dist/esm/utils/dynamic-loader.js +5 -5
  28. package/dist/esm/utils/dynamic-loader.js.map +1 -1
  29. package/dist/esm/utils/helpers/arkos-config.helpers.js +45 -28
  30. package/dist/esm/utils/helpers/arkos-config.helpers.js.map +1 -1
  31. package/dist/esm/utils/validate-schema.js +7 -7
  32. package/dist/esm/utils/validate-schema.js.map +1 -1
  33. package/dist/types/app.d.ts +4 -5
  34. package/dist/types/components/arkos-route-hook/index.d.ts +2 -2
  35. package/dist/types/modules/auth/auth.service.d.ts +9 -9
  36. package/dist/types/modules/base/base.controller.d.ts +3 -3
  37. package/dist/types/modules/base/base.middlewares.d.ts +3 -3
  38. package/dist/types/modules/base/base.service.d.ts +11 -10
  39. package/dist/types/modules/swagger/utils/helpers/openapi-schema-converter.d.ts +1 -1
  40. package/dist/types/types/arkos-prisma-input.d.ts +4 -1
  41. package/dist/types/types/new-arkos-config.d.ts +29 -34
  42. package/dist/types/types/router-config.d.ts +3 -3
  43. package/dist/types/utils/arkos-router/index.d.ts +5 -5
  44. package/dist/types/utils/arkos-router/types/index.d.ts +19 -19
  45. package/dist/types/utils/dynamic-loader.d.ts +1 -1
  46. package/dist/types/utils/helpers/arkos-config.helpers.d.ts +2 -1
  47. package/dist/types/utils/validate-schema.d.ts +1 -1
  48. package/package.json +1 -1
package/dist/esm/app.js CHANGED
@@ -1,24 +1,23 @@
1
- import "./utils/helpers/arkos-config.helpers.js";
2
- import express from "express";
3
- import setupApp from "./utils/setup-app.js";
4
- import initializeApp, { addGlobalErrorHandler } from "./utils/initialize-app.js";
5
- import { logAppStartup } from "./server.js";
6
- import runtimeCliCommander from "./utils/cli/utils/runtime-cli-commander.js";
7
- import { Server } from "http";
8
- import ExitError from "./utils/helpers/exit-error.js";
9
- import { applyArkosRouterProxy } from "./utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js";
10
- import { isProduction, validateArkosConfig, } from "./utils/helpers/arkos-config.helpers.js";
1
+ import { isProduction, validateArkosConfig, } from './utils/helpers/arkos-config.helpers.js';
2
+ import express from 'express';
3
+ import setupApp from './utils/setup-app.js';
4
+ import initializeApp, { addGlobalErrorHandler } from './utils/initialize-app.js';
5
+ import { logAppStartup } from './server.js';
6
+ import runtimeCliCommander from './utils/cli/utils/runtime-cli-commander.js';
7
+ import { Server } from 'http';
8
+ import ExitError from './utils/helpers/exit-error.js';
9
+ import { applyArkosRouterProxy } from './utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js';
11
10
  export const app = express();
12
11
  let appServer;
13
- export const docsLink = "https://www.arkosjs.com/docs/core-concepts/routing/setup#setting-up-your-app";
12
+ export const docsLink = 'https://www.arkosjs.com/docs/core-concepts/routing/setup#setting-up-your-app';
14
13
  let instanciated = false;
15
- export let state = "idle";
14
+ export let state = 'idle';
16
15
  export default function arkos() {
17
- if (process.env.__ARKOS_CLI !== "true")
16
+ if (process.env.__ARKOS_CLI !== 'true')
18
17
  throw ExitError(`Arkos.js application must be started the built-in cli ${isProduction() ? "'arkos start' in production" : `'arkos dev' in development`} see https://www.arkosjs.com/docs/getting-started/installation#7-set-up-packagejson-scripts`);
19
18
  if (instanciated)
20
19
  throw ExitError(`arkos() must be called only once, see ${docsLink}`);
21
- const app = applyArkosRouterProxy(express(), {}, "app");
20
+ const app = applyArkosRouterProxy(express(), {}, 'app');
22
21
  setupApp(app);
23
22
  instanciated = true;
24
23
  function loadApp() {
@@ -29,13 +28,13 @@ export default function arkos() {
29
28
  return _app;
30
29
  }
31
30
  app.build = function () {
32
- if (state === "built" || state === "building")
31
+ if (state === 'built' || state === 'building')
33
32
  throw ExitError(`app.build() must only be called once, see ${docsLink}`);
34
- if (state === "listening")
33
+ if (state === 'listening')
35
34
  throw ExitError(`app.build() must be called before app.listen(), see ${docsLink}`);
36
- state = "building";
35
+ state = 'building';
37
36
  const _app = loadApp();
38
- state = "built";
37
+ state = 'built';
39
38
  return _app;
40
39
  };
41
40
  const originalListen = app.listen.bind(app);
@@ -44,24 +43,24 @@ export default function arkos() {
44
43
  return cb || function () { };
45
44
  };
46
45
  app.listen = async function (...args) {
47
- process.env.__ARKOS_SERVER_LISTENER = "arkos";
48
- if (state === "listening")
46
+ process.env.__ARKOS_SERVER_LISTENER = 'arkos';
47
+ if (state === 'listening')
49
48
  throw ExitError(`app.listen() must only be called once, see ${docsLink}`);
50
- if (state === "building")
49
+ if (state === 'building')
51
50
  throw ExitError(`app.build() must be awaited before calling app.listen(), see ${docsLink}`);
52
- if (state === "idle") {
53
- state = "listening";
51
+ if (state === 'idle') {
52
+ state = 'listening';
54
53
  loadApp();
55
54
  }
56
55
  validateArkosConfig();
57
- const port = Number(process.env.__PORT || process.env.PORT || "8000");
58
- const host = process.env.__HOST || process.env.HOST || "0.0.0.0";
56
+ const port = Number(process.env.__PORT || process.env.PORT || '8000');
57
+ const host = process.env.__HOST || process.env.HOST || '0.0.0.0';
59
58
  process.send?.({ started: true });
60
- if (process.env.__SKIP_LISTEN == "true")
59
+ if (process.env.__SKIP_LISTEN == 'true')
61
60
  return appServer;
62
- if (args?.length === 0 || typeof args[0] === "function")
61
+ if (args?.length === 0 || typeof args[0] === 'function')
63
62
  appServer = originalListen(port, host, defaultCb(port, host, args[0]));
64
- else if (args[0] instanceof Server || typeof args[0] === "object")
63
+ else if (args[0] instanceof Server || typeof args[0] === 'object')
65
64
  appServer = args[0].listen(port, host, defaultCb(port, host, args[1]));
66
65
  return appServer;
67
66
  };
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,sCAAsC,CAAC;AAC9C,OAAO,OAAoB,MAAM,SAAS,CAAC;AAC3C,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,aAAa,EAAE,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,mBAAmB,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAmB,MAAM,EAAkB,MAAM,MAAM,CAAC;AAC/D,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6DAA6D,CAAC;AACpG,OAAO,EACL,YAAY,EACZ,mBAAmB,GACpB,MAAM,sCAAsC,CAAC;AAC9C,MAAM,CAAC,MAAM,GAAG,GAAoB,OAAO,EAAE,CAAC;AAE9C,IAAI,SAAgE,CAAC;AACrE,MAAM,CAAC,MAAM,QAAQ,GACnB,8EAA8E,CAAC;AACjF,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB,MAAM,CAAC,IAAI,KAAK,GAAa,MAAM,CAAC;AAwCpC,MAAM,CAAC,OAAO,UAAU,KAAK;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM;QACpC,MAAM,SAAS,CACb,yDAAyD,YAAY,EAAE,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,4BAA4B,6FAA6F,CACpO,CAAC;IAEJ,IAAI,YAAY;QACd,MAAM,SAAS,CAAC,yCAAyC,QAAQ,EAAE,CAAC,CAAC;IAEvE,MAAM,GAAG,GAAG,qBAAqB,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,KAAK,CAAiB,CAAC;IACxE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACd,YAAY,GAAG,IAAI,CAAC;IAIpB,SAAS,OAAO;QACd,IAAI,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW;YAAE,mBAAmB,CAAC,MAAM,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,KAAK,GAAG;QACV,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU;YAC3C,MAAM,SAAS,CAAC,6CAA6C,QAAQ,EAAE,CAAC,CAAC;QAC3E,IAAI,KAAK,KAAK,WAAW;YACvB,MAAM,SAAS,CACb,uDAAuD,QAAQ,EAAE,CAClE,CAAC;QAEJ,KAAK,GAAG,UAAU,CAAC;QACnB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,KAAK,GAAG,OAAO,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAA6B,CAAC;IAGxE,MAAM,SAAS,GAAG,CAChB,IAAqB,EACrB,IAAY,EACZ,EAAiB,EACjB,EAAE;QACF,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1B,OAAO,EAAE,IAAI,cAAa,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,GAAG,CAAC,MAAM,GAAG,KAAK,WAAU,GAAG,IAAW;QACxC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,OAAO,CAAC;QAE9C,IAAI,KAAK,KAAK,WAAW;YACvB,MAAM,SAAS,CAAC,8CAA8C,QAAQ,EAAE,CAAC,CAAC;QAC5E,IAAI,KAAK,KAAK,UAAU;YACtB,MAAM,SAAS,CACb,gEAAgE,QAAQ,EAAE,CAC3E,CAAC;QAEJ,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,KAAK,GAAG,WAAW,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,mBAAmB,EAAE,CAAC;QAEtB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAO,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;QAElE,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM;YAAE,OAAO,SAAS,CAAC;QAE1D,IAAK,IAAY,EAAE,MAAM,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU;YAC9D,SAAS,GAAG,cAAc,CACxB,IAAI,EACJ,IAAI,EACJ,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAiB,CAAC,CAC/C,CAAC;aACC,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,MAAM,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;YAC/D,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CACxB,IAAI,EACJ,IAAI,EACJ,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAiB,CAAC,CAC/C,CAAC;QAEJ,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import \"./utils/helpers/arkos-config.helpers\";\nimport express, { Express } from \"express\";\nimport setupApp from \"./utils/setup-app\";\nimport { Arkos } from \"./types/arkos\";\nimport initializeApp, { addGlobalErrorHandler } from \"./utils/initialize-app\";\nimport { logAppStartup } from \"./server\";\nimport runtimeCliCommander from \"./utils/cli/utils/runtime-cli-commander\";\nimport { IncomingMessage, Server, ServerResponse } from \"http\";\nimport ExitError from \"./utils/helpers/exit-error\";\nimport { applyArkosRouterProxy } from \"./utils/arkos-router/utils/helpers/apply-arkos-router-proxy\";\nimport {\n isProduction,\n validateArkosConfig,\n} from \"./utils/helpers/arkos-config.helpers\";\nexport const app: express.Express = express();\n\nlet appServer: Server<typeof IncomingMessage, typeof ServerResponse>;\nexport const docsLink =\n \"https://www.arkosjs.com/docs/core-concepts/routing/setup#setting-up-your-app\";\nlet instanciated = false;\ntype AppState = \"idle\" | \"building\" | \"built\" | \"listening\";\nexport let state: AppState = \"idle\";\n\n/**\n * Creates and configures an Arkos application instance.\n *\n * Arkos extends Express with a small set of methods for registering routers,\n * loading route/service hooks, and booting the application. All Arkos-specific\n * setup (`app.build()`) must happen before the app starts\n * accepting requests.\n *\n * @example\n * ```ts\n * // Simple setup\n * import arkos from \"arkos\";\n *\n * const app = arkos();\n *\n * app.use(reportsRouter);\n *\n * app.listen();\n * ```\n *\n * @example\n * ```ts\n * // Custom HTTP server (e.g. for WebSockets)\n * import arkos from \"arkos\";\n * import http from \"http\";\n *\n * const app = arkos();\n *\n * app.use(reportsRouter);\n *\n * await app.build();\n *\n * const server = http.createServer(app);\n * app.listen(server)\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/routing/setup}\n */\nexport default function arkos(): Arkos {\n if (process.env.__ARKOS_CLI !== \"true\")\n throw ExitError(\n `Arkos.js application must be started the built-in cli ${isProduction() ? \"'arkos start' in production\" : `'arkos dev' in development`} see https://www.arkosjs.com/docs/getting-started/installation#7-set-up-packagejson-scripts`\n );\n\n if (instanciated)\n throw ExitError(`arkos() must be called only once, see ${docsLink}`);\n\n const app = applyArkosRouterProxy(express(), {}, \"app\") as any as Arkos;\n setupApp(app);\n instanciated = true;\n\n\n\n function loadApp() {\n let _app = initializeApp(app);\n _app = addGlobalErrorHandler(_app);\n if (process.env.CLI_COMMAND) runtimeCliCommander.handle();\n return _app;\n }\n\n app.build = function() {\n if (state === \"built\" || state === \"building\")\n throw ExitError(`app.build() must only be called once, see ${docsLink}`);\n if (state === \"listening\")\n throw ExitError(\n `app.build() must be called before app.listen(), see ${docsLink}`\n );\n\n state = \"building\";\n const _app = loadApp();\n state = \"built\";\n return _app;\n };\n\n const originalListen = app.listen.bind(app) as any as Express[\"listen\"];\n type UserCallback = (err?: Error) => void;\n\n const defaultCb = (\n port: number | string,\n host: string,\n cb?: UserCallback\n ) => {\n logAppStartup(port, host);\n return cb || function() { };\n };\n\n app.listen = async function(...args: any[]): Promise<Server> {\n process.env.__ARKOS_SERVER_LISTENER = \"arkos\";\n\n if (state === \"listening\")\n throw ExitError(`app.listen() must only be called once, see ${docsLink}`);\n if (state === \"building\")\n throw ExitError(\n `app.build() must be awaited before calling app.listen(), see ${docsLink}`\n );\n\n if (state === \"idle\") {\n state = \"listening\";\n loadApp();\n }\n\n validateArkosConfig();\n\n const port = Number(process.env.__PORT || process.env.PORT || \"8000\");\n const host = process.env.__HOST! || process.env.HOST || \"0.0.0.0\";\n\n process.send?.({ started: true });\n if (process.env.__SKIP_LISTEN == \"true\") return appServer;\n\n if ((args as any)?.length === 0 || typeof args[0] === \"function\")\n appServer = originalListen(\n port,\n host,\n defaultCb(port, host, args[0] as UserCallback)\n );\n else if (args[0] instanceof Server || typeof args[0] === \"object\")\n appServer = args[0].listen(\n port,\n host,\n defaultCb(port, host, args[1] as UserCallback)\n );\n\n return appServer;\n };\n\n return app;\n}\n\nexport function getAppServer() {\n return appServer;\n}\n"]}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,mBAAmB,GACpB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,OAAoB,MAAM,SAAS,CAAC;AAC3C,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,aAAa,EAAE,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,mBAAmB,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAmB,MAAM,EAAkB,MAAM,MAAM,CAAC;AAC/D,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6DAA6D,CAAC;AACpG,MAAM,CAAC,MAAM,GAAG,GAAoB,OAAO,EAAE,CAAC;AAE9C,IAAI,SAAgE,CAAC;AACrE,MAAM,CAAC,MAAM,QAAQ,GACnB,8EAA8E,CAAC;AACjF,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB,MAAM,CAAC,IAAI,KAAK,GAAa,MAAM,CAAC;AAwCpC,MAAM,CAAC,OAAO,UAAU,KAAK;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM;QACpC,MAAM,SAAS,CACb,yDAAyD,YAAY,EAAE,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,4BAA4B,6FAA6F,CACpO,CAAC;IAEJ,IAAI,YAAY;QACd,MAAM,SAAS,CAAC,yCAAyC,QAAQ,EAAE,CAAC,CAAC;IAEvE,MAAM,GAAG,GAAG,qBAAqB,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,KAAK,CAAiB,CAAC;IACxE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACd,YAAY,GAAG,IAAI,CAAC;IAEpB,SAAS,OAAO;QACd,IAAI,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW;YAAE,mBAAmB,CAAC,MAAM,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,KAAK,GAAG;QACV,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU;YAC3C,MAAM,SAAS,CAAC,6CAA6C,QAAQ,EAAE,CAAC,CAAC;QAC3E,IAAI,KAAK,KAAK,WAAW;YACvB,MAAM,SAAS,CACb,uDAAuD,QAAQ,EAAE,CAClE,CAAC;QAEJ,KAAK,GAAG,UAAU,CAAC;QACnB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,KAAK,GAAG,OAAO,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAA6B,CAAC;IAGxE,MAAM,SAAS,GAAG,CAChB,IAAqB,EACrB,IAAY,EACZ,EAAiB,EACjB,EAAE;QACF,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1B,OAAO,EAAE,IAAI,cAAa,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,GAAG,CAAC,MAAM,GAAG,KAAK,WAAW,GAAG,IAAW;QACzC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,OAAO,CAAC;QAE9C,IAAI,KAAK,KAAK,WAAW;YACvB,MAAM,SAAS,CAAC,8CAA8C,QAAQ,EAAE,CAAC,CAAC;QAC5E,IAAI,KAAK,KAAK,UAAU;YACtB,MAAM,SAAS,CACb,gEAAgE,QAAQ,EAAE,CAC3E,CAAC;QAEJ,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,KAAK,GAAG,WAAW,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,mBAAmB,EAAE,CAAC;QAEtB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAO,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;QAElE,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM;YAAE,OAAO,SAAS,CAAC;QAE1D,IAAK,IAAY,EAAE,MAAM,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU;YAC9D,SAAS,GAAG,cAAc,CACxB,IAAI,EACJ,IAAI,EACJ,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAiB,CAAC,CAC/C,CAAC;aACC,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,MAAM,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;YAC/D,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CACxB,IAAI,EACJ,IAAI,EACJ,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAiB,CAAC,CAC/C,CAAC;QAEJ,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import {\n isProduction,\n validateArkosConfig,\n} from './utils/helpers/arkos-config.helpers';\nimport express, { Express } from 'express';\nimport setupApp from './utils/setup-app';\nimport { Arkos } from './types/arkos';\nimport initializeApp, { addGlobalErrorHandler } from './utils/initialize-app';\nimport { logAppStartup } from './server';\nimport runtimeCliCommander from './utils/cli/utils/runtime-cli-commander';\nimport { IncomingMessage, Server, ServerResponse } from 'http';\nimport ExitError from './utils/helpers/exit-error';\nimport { applyArkosRouterProxy } from './utils/arkos-router/utils/helpers/apply-arkos-router-proxy';\nexport const app: express.Express = express();\n\nlet appServer: Server<typeof IncomingMessage, typeof ServerResponse>;\nexport const docsLink =\n 'https://www.arkosjs.com/docs/core-concepts/routing/setup#setting-up-your-app';\nlet instanciated = false;\ntype AppState = 'idle' | 'building' | 'built' | 'listening';\nexport let state: AppState = 'idle';\n\n/**\n * Creates and configures an Arkos application instance.\n *\n * Arkos extends Express with a small set of methods for registering routers,\n * loading route/service hooks, and booting the application. All Arkos-specific\n * setup (`app.build()`) must happen before the app starts\n * accepting requests.\n *\n * @example\n * ```ts\n * // Simple setup\n * import arkos from \"arkos\";\n *\n * const app = arkos();\n *\n * app.use(reportsRouter);\n *\n * app.listen();\n * ```\n *\n * @example\n * ```ts\n * // Custom HTTP server (e.g. for WebSockets)\n * import arkos from \"arkos\";\n * import http from \"http\";\n *\n * const app = arkos();\n *\n * app.use(reportsRouter);\n *\n * await app.build();\n *\n * const server = http.createServer(app);\n * app.listen(server)\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/routing/setup}\n */\nexport default function arkos(): Arkos {\n if (process.env.__ARKOS_CLI !== 'true')\n throw ExitError(\n `Arkos.js application must be started the built-in cli ${isProduction() ? \"'arkos start' in production\" : `'arkos dev' in development`} see https://www.arkosjs.com/docs/getting-started/installation#7-set-up-packagejson-scripts`,\n );\n\n if (instanciated)\n throw ExitError(`arkos() must be called only once, see ${docsLink}`);\n\n const app = applyArkosRouterProxy(express(), {}, 'app') as any as Arkos;\n setupApp(app);\n instanciated = true;\n\n function loadApp() {\n let _app = initializeApp(app);\n _app = addGlobalErrorHandler(_app);\n if (process.env.CLI_COMMAND) runtimeCliCommander.handle();\n return _app;\n }\n\n app.build = function () {\n if (state === 'built' || state === 'building')\n throw ExitError(`app.build() must only be called once, see ${docsLink}`);\n if (state === 'listening')\n throw ExitError(\n `app.build() must be called before app.listen(), see ${docsLink}`,\n );\n\n state = 'building';\n const _app = loadApp();\n state = 'built';\n return _app;\n };\n\n const originalListen = app.listen.bind(app) as any as Express['listen'];\n type UserCallback = (err?: Error) => void;\n\n const defaultCb = (\n port: number | string,\n host: string,\n cb?: UserCallback,\n ) => {\n logAppStartup(port, host);\n return cb || function () {};\n };\n\n app.listen = async function (...args: any[]): Promise<Server> {\n process.env.__ARKOS_SERVER_LISTENER = 'arkos';\n\n if (state === 'listening')\n throw ExitError(`app.listen() must only be called once, see ${docsLink}`);\n if (state === 'building')\n throw ExitError(\n `app.build() must be awaited before calling app.listen(), see ${docsLink}`,\n );\n\n if (state === 'idle') {\n state = 'listening';\n loadApp();\n }\n\n validateArkosConfig();\n\n const port = Number(process.env.__PORT || process.env.PORT || '8000');\n const host = process.env.__HOST! || process.env.HOST || '0.0.0.0';\n\n process.send?.({ started: true });\n if (process.env.__SKIP_LISTEN == 'true') return appServer;\n\n if ((args as any)?.length === 0 || typeof args[0] === 'function')\n appServer = originalListen(\n port,\n host,\n defaultCb(port, host, args[0] as UserCallback),\n );\n else if (args[0] instanceof Server || typeof args[0] === 'object')\n appServer = args[0].listen(\n port,\n host,\n defaultCb(port, host, args[1] as UserCallback),\n );\n\n return appServer;\n };\n\n return app;\n}\n\nexport function getAppServer() {\n return appServer;\n}\n\n"]}
@@ -1,43 +1,47 @@
1
+ import { ArkosPrismaService } from '../../exports/services/index.js';
2
+ import ExitError from '../../utils/helpers/exit-error.js';
1
3
  export function ArkosRouteHook(moduleName, configs) {
2
4
  const store = {};
3
5
  const makeMethod = (name) => (config) => {
4
6
  store[name] = config;
5
7
  return proxy;
6
8
  };
9
+ if (configs?.service && !(configs.service instanceof ArkosPrismaService))
10
+ throw ExitError(`Invalid service configured for model "${moduleName}": expected an instance of BaseService, please make your service object extend the BaseService class see https://www.arkosjs.com/docs/reference/base-service`);
7
11
  const base = {
8
- __type: "ArkosRouteHook",
12
+ __type: 'ArkosRouteHook',
9
13
  moduleName,
10
14
  _store: store,
11
15
  _configs: configs || {},
12
16
  };
13
17
  const methods = {};
14
- if (moduleName === "auth") {
18
+ if (moduleName === 'auth') {
15
19
  for (const name of [
16
- "getMe",
17
- "login",
18
- "logout",
19
- "signup",
20
- "updateMe",
21
- "updatePassword",
20
+ 'getMe',
21
+ 'login',
22
+ 'logout',
23
+ 'signup',
24
+ 'updateMe',
25
+ 'updatePassword',
22
26
  ]) {
23
27
  methods[name] = makeMethod(name);
24
28
  }
25
29
  }
26
- else if (moduleName === "file-upload" || moduleName === "fileUpload") {
27
- for (const name of ["findFile", "uploadFile", "updateFile", "deleteFile"]) {
30
+ else if (moduleName === 'file-upload' || moduleName === 'fileUpload') {
31
+ for (const name of ['findFile', 'uploadFile', 'updateFile', 'deleteFile']) {
28
32
  methods[name] = makeMethod(name);
29
33
  }
30
34
  }
31
35
  else {
32
36
  for (const name of [
33
- "createOne",
34
- "findOne",
35
- "findMany",
36
- "updateOne",
37
- "deleteOne",
38
- "createMany",
39
- "updateMany",
40
- "deleteMany",
37
+ 'createOne',
38
+ 'findOne',
39
+ 'findMany',
40
+ 'updateOne',
41
+ 'deleteOne',
42
+ 'createMany',
43
+ 'updateMany',
44
+ 'deleteMany',
41
45
  ]) {
42
46
  methods[name] = makeMethod(name);
43
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/arkos-route-hook/index.ts"],"names":[],"mappings":"AAkCA,MAAM,UAAU,cAAc,CAC5B,UAAa,EAAE,OAKd;IAED,MAAM,KAAK,GAAqB,EAAE,CAAC;IAEnC,MAAM,UAAU,GACd,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,MAAkC,EAAE,EAAE;QACvD,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEJ,MAAM,IAAI,GAAG;QACX,MAAM,EAAE,gBAAyB;QACjC,UAAU;QACV,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO,IAAI,EAAE;KACxB,CAAC;IAEF,MAAM,OAAO,GAGT,EAAE,CAAC;IAEP,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI;YACjB,OAAO;YACP,OAAO;YACP,QAAQ;YACR,QAAQ;YACR,UAAU;YACV,gBAAgB;SACjB,EAAE,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;SAAM,IAAI,UAAU,KAAK,aAAa,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;QACvE,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI;YACjB,WAAW;YACX,SAAS;YACT,UAAU;YACV,WAAW;YACX,WAAW;YACX,YAAY;YACZ,YAAY;YACZ,YAAY;SACb,EAAE,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE3C,OAAO,KAA2C,CAAC;AACrD,CAAC","sourcesContent":["import { ArkosPrismaService } from \"../../exports/services\";\nimport {\n ArkosModuleType,\n ArkosRouteHookReturn,\n ArkosRouteHookMethodConfig,\n} from \"./types\";\n\ninterface InterceptorStore {\n [methodName: string]: ArkosRouteHookMethodConfig;\n}\n\n/**\n * Creates an interceptor for a built-in Arkos module or a generated model route.\n *\n * The returned instance exposes only the methods relevant to that module,\n * and is registered into the app via `app.load()`.\n *\n * @param moduleName - The module to intercept. Use `\"auth\"` or `\"file-upload\"`\n * for built-in modules, or any prisma model name string for generated CRUD routes.\n *\n * @example\n * ```ts\n * const userRouteHook = ArkosRouteHook(\"user\");\n *\n * userRouteHook.createOne({\n * validation: { body: CreateUserSchema },\n * before: [sanitize],\n * after: [notify]\n * });\n *\n * app.load(userRouteHook);\n * ```\n * @see {@link https://www.arkosjs.com/docs/core-concepts/components/route-hooks}\n */\nexport function ArkosRouteHook<T extends ArkosModuleType>(\n moduleName: T, configs?: {\n /**\n * ArkosPrismaService instace for such model\n */\n service?: ArkosPrismaService<T>\n }\n): ArkosRouteHookReturn<T> {\n const store: InterceptorStore = {};\n\n const makeMethod =\n (name: string) => (config: ArkosRouteHookMethodConfig) => {\n store[name] = config;\n return proxy;\n };\n\n const base = {\n __type: \"ArkosRouteHook\" as const,\n moduleName,\n _store: store,\n _configs: configs || {},\n };\n\n const methods: Record<\n string,\n (config: ArkosRouteHookMethodConfig) => unknown\n > = {};\n\n if (moduleName === \"auth\") {\n for (const name of [\n \"getMe\",\n \"login\",\n \"logout\",\n \"signup\",\n \"updateMe\",\n \"updatePassword\",\n ]) {\n methods[name] = makeMethod(name);\n }\n } else if (moduleName === \"file-upload\" || moduleName === \"fileUpload\") {\n for (const name of [\"findFile\", \"uploadFile\", \"updateFile\", \"deleteFile\"]) {\n methods[name] = makeMethod(name);\n }\n } else {\n for (const name of [\n \"createOne\",\n \"findOne\",\n \"findMany\",\n \"updateOne\",\n \"deleteOne\",\n \"createMany\",\n \"updateMany\",\n \"deleteMany\",\n ]) {\n methods[name] = makeMethod(name);\n }\n }\n\n const proxy = Object.assign(base, methods);\n\n return proxy as unknown as ArkosRouteHookReturn<T>;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/arkos-route-hook/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,SAAS,MAAM,gCAAgC,CAAC;AAkCvD,MAAM,UAAU,cAAc,CAC5B,UAAa,EACb,OAKC;IAED,MAAM,KAAK,GAAqB,EAAE,CAAC;IAEnC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,MAAkC,EAAE,EAAE;QAC1E,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,YAAY,kBAAkB,CAAC;QACtE,MAAM,SAAS,CACb,yCAAyC,UAAU,8JAA8J,CAClN,CAAC;IAEJ,MAAM,IAAI,GAAG;QACX,MAAM,EAAE,gBAAyB;QACjC,UAAU;QACV,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO,IAAI,EAAE;KACxB,CAAC;IAEF,MAAM,OAAO,GAGT,EAAE,CAAC;IAEP,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI;YACjB,OAAO;YACP,OAAO;YACP,QAAQ;YACR,QAAQ;YACR,UAAU;YACV,gBAAgB;SACjB,EAAE,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;SAAM,IAAI,UAAU,KAAK,aAAa,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;QACvE,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI;YACjB,WAAW;YACX,SAAS;YACT,UAAU;YACV,WAAW;YACX,WAAW;YACX,YAAY;YACZ,YAAY;YACZ,YAAY;SACb,EAAE,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE3C,OAAO,KAA2C,CAAC;AACrD,CAAC","sourcesContent":["import { ArkosPrismaService } from '../../exports/services';\nimport ExitError from '../../utils/helpers/exit-error';\nimport {\n ArkosModuleType,\n ArkosRouteHookReturn,\n ArkosRouteHookMethodConfig,\n} from './types';\n\ninterface InterceptorStore {\n [methodName: string]: ArkosRouteHookMethodConfig;\n}\n\n/**\n * Creates an interceptor for a built-in Arkos module or a generated model route.\n *\n * The returned instance exposes only the methods relevant to that module,\n * and is registered into the app via `app.load()`.\n *\n * @param moduleName - The module to intercept. Use `\"auth\"` or `\"file-upload\"`\n * for built-in modules, or any prisma model name string for generated CRUD routes.\n *\n * @example\n * ```ts\n * const userRouteHook = ArkosRouteHook(\"user\");\n *\n * userRouteHook.createOne({\n * validation: { body: CreateUserSchema },\n * before: [sanitize],\n * after: [notify]\n * });\n *\n * app.load(userRouteHook);\n * ```\n * @see {@link https://www.arkosjs.com/docs/core-concepts/components/route-hooks}\n */\nexport function ArkosRouteHook<T extends ArkosModuleType>(\n moduleName: T,\n configs?: {\n /**\n * ArkosPrismaService instace for such model\n */\n service?: ArkosPrismaService<T>;\n },\n): ArkosRouteHookReturn<T> {\n const store: InterceptorStore = {};\n\n const makeMethod = (name: string) => (config: ArkosRouteHookMethodConfig) => {\n store[name] = config;\n return proxy;\n };\n\n if (configs?.service && !(configs.service instanceof ArkosPrismaService))\n throw ExitError(\n `Invalid service configured for model \"${moduleName}\": expected an instance of BaseService, please make your service object extend the BaseService class see https://www.arkosjs.com/docs/reference/base-service`,\n );\n\n const base = {\n __type: 'ArkosRouteHook' as const,\n moduleName,\n _store: store,\n _configs: configs || {},\n };\n\n const methods: Record<\n string,\n (config: ArkosRouteHookMethodConfig) => unknown\n > = {};\n\n if (moduleName === 'auth') {\n for (const name of [\n 'getMe',\n 'login',\n 'logout',\n 'signup',\n 'updateMe',\n 'updatePassword',\n ]) {\n methods[name] = makeMethod(name);\n }\n } else if (moduleName === 'file-upload' || moduleName === 'fileUpload') {\n for (const name of ['findFile', 'uploadFile', 'updateFile', 'deleteFile']) {\n methods[name] = makeMethod(name);\n }\n } else {\n for (const name of [\n 'createOne',\n 'findOne',\n 'findMany',\n 'updateOne',\n 'deleteOne',\n 'createMany',\n 'updateMany',\n 'deleteMany',\n ]) {\n methods[name] = makeMethod(name);\n }\n }\n\n const proxy = Object.assign(base, methods);\n\n return proxy as unknown as ArkosRouteHookReturn<T>;\n}\n\n"]}
@@ -1,24 +1,24 @@
1
- import jwt from "jsonwebtoken";
2
- import bcrypt from "bcryptjs";
3
- import catchAsync from "../error-handler/utils/catch-async.js";
4
- import AppError from "../error-handler/utils/app-error.js";
5
- import arkosEnv from "../../utils/arkos-env.js";
6
- import { getPrismaInstance } from "../../utils/helpers/prisma.helpers.js";
7
- import { toMs } from "./utils/helpers/auth.controller.helpers.js";
8
- import { invaliAuthTokenError, loginRequiredError, } from "./utils/auth-error-objects.js";
9
- import authActionService from "./utils/services/auth-action.service.js";
10
- import { getArkosConfig, isAuthenticationEnabled, isUsingAuthentication, } from "../../utils/helpers/arkos-config.helpers.js";
11
- import { getUserFileExtension } from "../../utils/helpers/fs.helpers.js";
12
- import { authenticationDocsLinks } from "./utils/docs-links.js";
13
- import authHookManager from "./utils/auth-hooks-manager.js";
1
+ import jwt from 'jsonwebtoken';
2
+ import bcrypt from 'bcryptjs';
3
+ import catchAsync from '../error-handler/utils/catch-async.js';
4
+ import AppError from '../error-handler/utils/app-error.js';
5
+ import arkosEnv from '../../utils/arkos-env.js';
6
+ import { getPrismaInstance } from '../../utils/helpers/prisma.helpers.js';
7
+ import { toMs } from './utils/helpers/auth.controller.helpers.js';
8
+ import { invaliAuthTokenError, loginRequiredError, } from './utils/auth-error-objects.js';
9
+ import authActionService from './utils/services/auth-action.service.js';
10
+ import { getArkosConfig, isAuthenticationEnabled, isUsingAuthentication, } from '../../utils/helpers/arkos-config.helpers.js';
11
+ import { getUserFileExtension } from '../../utils/helpers/fs.helpers.js';
12
+ import { authenticationDocsLinks } from './utils/docs-links.js';
13
+ import authHookManager from './utils/auth-hooks-manager.js';
14
14
  export class AuthService {
15
15
  actionsPerResource = {};
16
16
  signJwtToken(id, expiresIn, secret) {
17
17
  const { authentication: configs } = getArkosConfig();
18
- if (process.env.ARKOS_BUILD === "true" &&
18
+ if (process.env.ARKOS_BUILD === 'true' &&
19
19
  !process.env.JWT_SECRET &&
20
20
  !configs?.jwt?.secret)
21
- throw new AppError("Missing JWT secret on production!", 500, "MissingJWTOnProduction");
21
+ throw new AppError('Missing JWT secret on production!', 500, 'MissingJWTOnProduction');
22
22
  secret =
23
23
  secret ||
24
24
  configs?.jwt?.secret ||
@@ -36,10 +36,10 @@ export class AuthService {
36
36
  const arkosConfig = getArkosConfig();
37
37
  const authConfigs = arkosConfig?.authentication;
38
38
  if (!req)
39
- throw new Error("Missing req object in order get jwt cookie options");
39
+ throw new Error('Missing req object in order get jwt cookie options');
40
40
  const sameSite = authConfigs?.jwt?.cookie?.sameSite ||
41
41
  process.env.JWT_COOKIE_SAME_SITE ||
42
- "lax";
42
+ 'lax';
43
43
  return {
44
44
  expires: new Date(Date.now() +
45
45
  Number(toMs(authConfigs?.jwt?.expiresIn ||
@@ -47,16 +47,16 @@ export class AuthService {
47
47
  arkosEnv.JWT_EXPIRES_IN))),
48
48
  httpOnly: authConfigs?.jwt?.cookie?.httpOnly ??
49
49
  (process.env.JWT_COOKIE_HTTP_ONLY !== undefined
50
- ? process.env.JWT_COOKIE_HTTP_ONLY === "true"
50
+ ? process.env.JWT_COOKIE_HTTP_ONLY === 'true'
51
51
  : undefined) ??
52
52
  true,
53
53
  secure: (() => {
54
54
  if (authConfigs?.jwt?.cookie?.secure !== undefined)
55
55
  return authConfigs?.jwt?.cookie?.secure;
56
56
  else if (process.env.JWT_COOKIE_SECURE !== undefined)
57
- return process.env.JWT_COOKIE_SECURE === "true";
57
+ return process.env.JWT_COOKIE_SECURE === 'true';
58
58
  else
59
- return req.secure || req.headers["x-forwarded-proto"] === "https";
59
+ return req.secure || req.headers['x-forwarded-proto'] === 'https';
60
60
  })(),
61
61
  sameSite,
62
62
  domain: authConfigs?.jwt?.cookie?.domain || process.env.JWT_COOKIE_DOMAIN,
@@ -81,10 +81,10 @@ export class AuthService {
81
81
  }
82
82
  async verifyJwtToken(token, secret) {
83
83
  const { authentication: configs } = getArkosConfig();
84
- if (process.env.ARKOS_BUILD === "true" &&
84
+ if (process.env.ARKOS_BUILD === 'true' &&
85
85
  !process.env.JWT_SECRET &&
86
86
  !configs?.jwt?.secret)
87
- throw new AppError("Missing JWT secret in production", 500, "MissingJWTSecretInProduction");
87
+ throw new AppError('Missing JWT secret in production', 500, 'MissingJWTSecretInProduction');
88
88
  secret =
89
89
  secret ||
90
90
  configs?.jwt?.secret ||
@@ -108,26 +108,26 @@ export class AuthService {
108
108
  }
109
109
  }
110
110
  isWildcardAccess(config) {
111
- return config === "*";
111
+ return config === '*';
112
112
  }
113
113
  isRoleList(config) {
114
114
  return Array.isArray(config);
115
115
  }
116
116
  isAccessRules(config) {
117
- return (typeof config === "object" && config !== null && !Array.isArray(config));
117
+ return (typeof config === 'object' && config !== null && !Array.isArray(config));
118
118
  }
119
119
  normalizeRuleToRoles(rule) {
120
120
  if (!rule)
121
121
  return [];
122
- if (rule === "*")
123
- return ["*"];
122
+ if (rule === '*')
123
+ return ['*'];
124
124
  if (Array.isArray(rule))
125
125
  return rule;
126
- return rule.roles === "*" ? ["*"] : (rule.roles ?? []);
126
+ return rule.roles === '*' ? ['*'] : (rule.roles ?? []);
127
127
  }
128
128
  resolveAuthorizedRoles(action, accessControl) {
129
129
  if (this.isWildcardAccess(accessControl))
130
- return ["*"];
130
+ return ['*'];
131
131
  if (this.isRoleList(accessControl))
132
132
  return accessControl;
133
133
  if (this.isAccessRules(accessControl))
@@ -136,10 +136,10 @@ export class AuthService {
136
136
  }
137
137
  checkStaticAccessControl(user, action, accessControl) {
138
138
  if (!user?.role && !user.roles)
139
- throw Error("Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.");
139
+ throw Error('Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.');
140
140
  let authorizedRoles = this.resolveAuthorizedRoles(action, accessControl);
141
141
  const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];
142
- return (authorizedRoles?.[0] === "*" ||
142
+ return (authorizedRoles?.[0] === '*' ||
143
143
  !!userRoles.some((role) => authorizedRoles.includes(role)));
144
144
  }
145
145
  async checkDynamicAccessControl(userId, action, resource) {
@@ -164,44 +164,44 @@ export class AuthService {
164
164
  }),
165
165
  ]);
166
166
  if (userPermission)
167
- return userPermission.effect === "Allow";
167
+ return userPermission.effect === 'Allow';
168
168
  return !!hasRolePermission;
169
169
  }
170
- extractRequestToken(req, cookie = "arkos_access_token") {
170
+ extractRequestToken(req, cookie = 'arkos_access_token') {
171
171
  let token = null;
172
172
  if (req?.headers?.authorization &&
173
- req?.headers?.authorization.startsWith("Bearer") &&
174
- req?.headers?.authorization.split?.(" ")?.[1])
175
- token = req?.headers?.authorization.split(" ")[1];
173
+ req?.headers?.authorization.startsWith('Bearer') &&
174
+ req?.headers?.authorization.split?.(' ')?.[1])
175
+ token = req?.headers?.authorization.split(' ')[1];
176
176
  if (!token &&
177
- req?.cookies?.arkos_access_token !== "no-token" &&
177
+ req?.cookies?.arkos_access_token !== 'no-token' &&
178
178
  req.cookies)
179
179
  token = req?.cookies?.[cookie];
180
180
  return token;
181
181
  }
182
- extractSocketToken(socket, key = "token") {
182
+ extractSocketToken(socket, key = 'token') {
183
183
  return (socket.handshake.auth?.[key] ||
184
- socket.handshake.headers?.authorization?.replace("Bearer ", ""));
184
+ socket.handshake.headers?.authorization?.replace('Bearer ', ''));
185
185
  }
186
- async validateDecodedUser(decoded, action = "default") {
186
+ async validateDecodedUser(decoded, action = 'default') {
187
187
  const prisma = getPrismaInstance();
188
188
  const user = await prisma.user.findUnique({
189
189
  where: { id: decoded.id },
190
190
  });
191
191
  if (!user)
192
- throw new AppError("The user belonging to this token no longer exists", 401, "UserNoLongerExists");
193
- if (action !== "logout" &&
192
+ throw new AppError('The user belonging to this token no longer exists', 401, 'UserNoLongerExists');
193
+ if (action !== 'logout' &&
194
194
  this.userChangedPasswordAfter(user, decoded.iat))
195
- throw new AppError("User recently changed password! Please log in again.", 401, "PasswordChanged");
195
+ throw new AppError('User recently changed password! Please log in again.', 401, 'PasswordChanged');
196
196
  return user;
197
197
  }
198
- async getAuthenticatedUser(ctx, action = "default") {
198
+ async getAuthenticatedUser(ctx, action = 'default') {
199
199
  if (!isAuthenticationEnabled())
200
200
  throw Error(`Trying to call authService.getAuthenticatedUser without setting up authentication in arkos.config.${getUserFileExtension()}, see ${authenticationDocsLinks.setup}`);
201
201
  let token = null;
202
- if ("headers" in ctx)
202
+ if ('headers' in ctx)
203
203
  token = this.extractRequestToken(ctx);
204
- else if ("join" in ctx)
204
+ else if ('join' in ctx)
205
205
  token = this.extractSocketToken(ctx);
206
206
  if (!token)
207
207
  return null;
@@ -213,7 +213,7 @@ export class AuthService {
213
213
  await authHookManager.runAuthenticate({ context: req, done: next }, async (req) => {
214
214
  if (!isAuthenticationEnabled())
215
215
  return null;
216
- const user = (await this.getAuthenticatedUser(req, req.path.includes("logout") ? "logout" : "default"));
216
+ const user = (await this.getAuthenticatedUser(req, req.path.includes('logout') ? 'logout' : 'default'));
217
217
  if (!user)
218
218
  throw loginRequiredError;
219
219
  return user;
@@ -229,23 +229,23 @@ export class AuthService {
229
229
  }
230
230
  permission(action, resource, accessControl) {
231
231
  const stack = new Error().stack;
232
- if (stack?.includes("node_modules/express/lib/router/index.js"))
233
- throw new Error("authService.permission() should be called during application initialization level.");
232
+ if (stack?.includes('node_modules/express/lib/router/index.js'))
233
+ throw new Error('authService.permission() should be called during application initialization level.');
234
234
  authActionService.add(action, resource, accessControl);
235
235
  return async (user) => {
236
236
  const configs = getArkosConfig();
237
237
  if (!isUsingAuthentication())
238
- throw Error("Validation Error: Trying to use authService.permission without setting up authentication.");
238
+ throw Error('Validation Error: Trying to use authService.permission without setting up authentication.');
239
239
  if (!isAuthenticationEnabled())
240
240
  return false;
241
241
  if (!user)
242
242
  throw loginRequiredError;
243
243
  if (user?.isSuperUser)
244
244
  return true;
245
- if (configs?.authentication?.mode === "dynamic") {
245
+ if (configs?.authentication?.mode === 'dynamic') {
246
246
  return await this.checkDynamicAccessControl(user?.id, action, resource);
247
247
  }
248
- else if (configs?.authentication?.mode === "static") {
248
+ else if (configs?.authentication?.mode === 'static') {
249
249
  return (!!accessControl &&
250
250
  this.checkStaticAccessControl(user, action, accessControl));
251
251
  }
@@ -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 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 AccessControlRules,\n DetailedAccessControlRule,\n} from \"../../types/auth\";\nimport { MsDuration, toMs } from \"./utils/helpers/auth.controller.helpers\";\nimport {\n invaliAuthTokenError,\n loginRequiredError,\n} from \"./utils/auth-error-objects\";\nimport authActionService from \"./utils/services/auth-action.service\";\nimport {\n getArkosConfig,\n isAuthenticationEnabled,\n isUsingAuthentication,\n} from \"../../utils/helpers/arkos-config.helpers\";\nimport { CookieOptions } from \"express\";\nimport { getUserFileExtension } from \"../../utils/helpers/fs.helpers\";\nimport { authenticationDocsLinks } from \"./utils/docs-links\";\nimport authHookManager from \"./utils/auth-hooks-manager\";\nimport { ArkosSocket } from \"../../components/arkos-gateway/types\";\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 if (authConfigs?.jwt?.cookie?.secure !== undefined)\n return authConfigs?.jwt?.cookie?.secure;\n else if (process.env.JWT_COOKIE_SECURE !== undefined)\n return process.env.JWT_COOKIE_SECURE === \"true\";\n else return req.secure || req.headers[\"x-forwarded-proto\"] === \"https\";\n })(),\n sameSite,\n domain: authConfigs?.jwt?.cookie?.domain || process.env.JWT_COOKIE_DOMAIN,\n ...arkosConfig?.authentication?.jwt?.cookie,\n } as CookieOptions;\n }\n\n /**\n * Is used by default internally by Arkos under `ArkosPrismaService` 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 `ArkosPrismaService` class will automatically hash the password field using `authService.hashPassword` by default.\n *\n * So now before `ArkosPrismaService` 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 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(new Date(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 try {\n const decoded = (await new Promise((resolve, reject) => {\n jwt.verify(token, secret, (err, decoded) => {\n if (err) reject(err);\n else resolve(decoded as AuthJwtPayload);\n });\n })) as AuthJwtPayload;\n\n if (!decoded?.id) throw invaliAuthTokenError;\n\n return decoded;\n } catch (err) {\n throw invaliAuthTokenError;\n }\n }\n\n private isWildcardAccess(config: AccessControlConfig): config is \"*\" {\n return config === \"*\";\n }\n\n private isRoleList(config: AccessControlConfig): config is string[] {\n return Array.isArray(config);\n }\n\n private isAccessRules(\n config: AccessControlConfig\n ): config is Partial<AccessControlRules> {\n return (\n typeof config === \"object\" && config !== null && !Array.isArray(config)\n );\n }\n\n private normalizeRuleToRoles(\n rule: string[] | DetailedAccessControlRule | \"*\" | undefined\n ): string[] {\n if (!rule) return [];\n if (rule === \"*\") return [\"*\"];\n if (Array.isArray(rule)) return rule;\n return rule.roles === \"*\" ? [\"*\"] : (rule.roles ?? []);\n }\n\n private resolveAuthorizedRoles(\n action: AccessAction,\n accessControl: AccessControlConfig\n ): string[] {\n if (this.isWildcardAccess(accessControl)) return [\"*\"];\n if (this.isRoleList(accessControl)) return accessControl;\n if (this.isAccessRules(accessControl))\n return this.normalizeRuleToRoles(accessControl[action]);\n return [];\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 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 = this.resolveAuthorizedRoles(action, accessControl);\n\n const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];\n\n return (\n authorizedRoles?.[0] === \"*\" ||\n !!userRoles.some((role: string) => authorizedRoles.includes(role))\n );\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 async checkDynamicAccessControl(\n userId: string,\n action: string,\n resource: string\n ) {\n const prisma = getPrismaInstance();\n\n const [userPermission, hasRolePermission] = await Promise.all([\n prisma.userPermission\n ? prisma.userPermission.findFirst({\n where: { userId, permission: { resource, action } },\n select: { effect: true },\n })\n : Promise.resolve(null),\n\n prisma.userRole.findFirst({\n where: {\n userId,\n role: {\n permissions: {\n some: { resource, action },\n },\n },\n },\n select: { id: true },\n }),\n ]);\n\n if (userPermission) return userPermission.effect === \"Allow\";\n return !!hasRolePermission;\n }\n\n private extractRequestToken(\n req: ArkosRequest,\n cookie: \"arkos_access_token\" = \"arkos_access_token\"\n ) {\n let token: string | null = null;\n\n if (\n req?.headers?.authorization &&\n req?.headers?.authorization.startsWith(\"Bearer\") &&\n req?.headers?.authorization.split?.(\" \")?.[1]\n )\n token = req?.headers?.authorization.split(\" \")[1];\n\n if (\n !token &&\n req?.cookies?.arkos_access_token !== \"no-token\" &&\n req.cookies\n )\n token = req?.cookies?.[cookie];\n\n return token;\n }\n\n private extractSocketToken(socket: ArkosSocket, key: \"token\" = \"token\") {\n return (\n socket.handshake.auth?.[key] ||\n socket.handshake.headers?.authorization?.replace(\"Bearer \", \"\")\n );\n }\n\n async validateDecodedUser(\n decoded: AuthJwtPayload,\n action: \"logout\" | \"default\" = \"default\"\n ): Promise<User> {\n const prisma = getPrismaInstance();\n const user = await (prisma as any).user.findUnique({\n where: { id: decoded.id },\n });\n\n if (!user)\n throw new AppError(\n \"The user belonging to this token no longer exists\",\n 401,\n \"UserNoLongerExists\"\n );\n\n if (\n action !== \"logout\" &&\n this.userChangedPasswordAfter(user, decoded.iat!)\n )\n throw new AppError(\n \"User recently changed password! Please log in again.\",\n 401,\n \"PasswordChanged\"\n );\n\n return user;\n }\n\n /**\n * Processes the cookies or authoriation token and returns the user.\n *\n * @param ctx | socket\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(\n ctx: ArkosRequest | ArkosSocket,\n action: \"logout\" | \"default\" = \"default\"\n ): Promise<User | null> {\n if (!isAuthenticationEnabled())\n throw Error(\n `Trying to call authService.getAuthenticatedUser without setting up authentication in arkos.config.${getUserFileExtension()}, see ${authenticationDocsLinks.setup}`\n );\n\n let token: string | null = null;\n\n if (\"headers\" in ctx) token = this.extractRequestToken(ctx);\n else if (\"join\" in ctx) token = this.extractSocketToken(ctx);\n\n if (!token) return null;\n\n const decoded = await this.verifyJwtToken(token);\n ctx.accessToken = token;\n\n return this.validateDecodedUser(decoded, action);\n }\n\n /**\n * Middleware to authenticate the request by extracting and verifying the JWT token and setting `req.user`.\n *\n * Runs `authentication.hooks.authenticate` before/after the authentication logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — extracts and verifies the JWT token, sets `req.user`.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if core logic throws — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * On custom routes, hooks defined in `arkosConfig` still apply since they are baked into this method.\n *\n * @example\n * ```ts\n * // custom route - hooks still run\n * router.get(\"/custom\", authService.authenticate, handler);\n * ```\n *\n * @example\n * ```ts\n * // skip built-in auth from a before hook\n * before: (ctx) => {\n * ctx.req.user = myCustomAuth(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks}\n */\n authenticate = catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n await authHookManager.runAuthenticate(\n { context: req, done: next },\n async (req): Promise<any> => {\n if (!isAuthenticationEnabled()) return null;\n const user = (await this.getAuthenticatedUser(\n req,\n req.path.includes(\"logout\") ? \"logout\" : \"default\"\n )) as User;\n if (!user) throw loginRequiredError;\n return user;\n }\n );\n }\n );\n\n /**\n * Middleware to authorize the authenticated user for a given action on a resource.\n *\n * Runs `authentication.hooks.authorize` before/after the authorization logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — checks user role/permissions against the access control rules.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if authorization fails — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * @param resource - The resource being accessed, in kebabCase (e.g. `\"product\"`, `\"cart-item\"`)\n * @param action - The action being performed (e.g. `\"View\"`, `\"Create\"`, `\"Delete\"`)\n * @param rule - Access control rules for this action. Accepts a role list, a wildcard, or a `DetailedAccessControlRule`.\n *\n * @example\n * ```ts\n * router.delete(\"/products/:id\",\n * authService.authenticate,\n * authService.authorize(\"product\", \"Delete\", [\"admin\"]),\n * handler\n * );\n * ```\n *\n * @example\n * ```ts\n * // skip built-in authorization from a before hook\n * before: (ctx) => {\n * ctx.req.user.role = myCustomRoleResolver(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks#authorize}\n * @since v1.6.0-beta\n */\n authorize(\n action: AccessAction,\n resource: string,\n rule?: string[] | DetailedAccessControlRule | \"*\"\n ): ArkosRequestHandler {\n const authAction = authActionService.add(action, resource, {\n [action]: rule,\n });\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n await authHookManager.runAuthorize(\n { context: req, done: next },\n authAction\n );\n }\n );\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: User | undefined): Promise<boolean> => {\n // getArkosConfig must not be called the same time as arkos.init()\n const configs = getArkosConfig();\n\n if (!isUsingAuthentication())\n throw Error(\n \"Validation Error: Trying to use authService.permission without setting up authentication.\"\n );\n\n if (!isAuthenticationEnabled()) return false;\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 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 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 AccessControlRules,\n DetailedAccessControlRule,\n} from '../../types/auth';\nimport { MsDuration, toMs } from './utils/helpers/auth.controller.helpers';\nimport {\n invaliAuthTokenError,\n loginRequiredError,\n} from './utils/auth-error-objects';\nimport authActionService from './utils/services/auth-action.service';\nimport {\n getArkosConfig,\n isAuthenticationEnabled,\n isUsingAuthentication,\n} from '../../utils/helpers/arkos-config.helpers';\nimport { CookieOptions } from 'express';\nimport { getUserFileExtension } from '../../utils/helpers/fs.helpers';\nimport { authenticationDocsLinks } from './utils/docs-links';\nimport authHookManager from './utils/auth-hooks-manager';\nimport { ArkosSocket } from '../../components/arkos-gateway/types';\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' | 'lax' | 'strict' | 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 if (authConfigs?.jwt?.cookie?.secure !== undefined)\n return authConfigs?.jwt?.cookie?.secure;\n else if (process.env.JWT_COOKIE_SECURE !== undefined)\n return process.env.JWT_COOKIE_SECURE === 'true';\n else return req.secure || req.headers['x-forwarded-proto'] === 'https';\n })(),\n sameSite,\n domain: authConfigs?.jwt?.cookie?.domain || process.env.JWT_COOKIE_DOMAIN,\n ...arkosConfig?.authentication?.jwt?.cookie,\n } as CookieOptions;\n }\n\n /**\n * Is used by default internally by Arkos under `ArkosPrismaService` 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 `ArkosPrismaService` class will automatically hash the password field using `authService.hashPassword` by default.\n *\n * So now before `ArkosPrismaService` 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 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(new Date(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 try {\n const decoded = (await new Promise((resolve, reject) => {\n jwt.verify(token, secret, (err, decoded) => {\n if (err) reject(err);\n else resolve(decoded as AuthJwtPayload);\n });\n })) as AuthJwtPayload;\n\n if (!decoded?.id) throw invaliAuthTokenError;\n\n return decoded;\n } catch (err) {\n throw invaliAuthTokenError;\n }\n }\n\n private isWildcardAccess(config: AccessControlConfig): config is '*' {\n return config === '*';\n }\n\n private isRoleList(config: AccessControlConfig): config is string[] {\n return Array.isArray(config);\n }\n\n private isAccessRules(\n config: AccessControlConfig,\n ): config is Partial<AccessControlRules> {\n return (\n typeof config === 'object' && config !== null && !Array.isArray(config)\n );\n }\n\n private normalizeRuleToRoles(\n rule: string[] | DetailedAccessControlRule | '*' | undefined,\n ): string[] {\n if (!rule) return [];\n if (rule === '*') return ['*'];\n if (Array.isArray(rule)) return rule;\n return rule.roles === '*' ? ['*'] : (rule.roles ?? []);\n }\n\n private resolveAuthorizedRoles(\n action: AccessAction,\n accessControl: AccessControlConfig,\n ): string[] {\n if (this.isWildcardAccess(accessControl)) return ['*'];\n if (this.isRoleList(accessControl)) return accessControl;\n if (this.isAccessRules(accessControl))\n return this.normalizeRuleToRoles(accessControl[action]);\n return [];\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 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 = this.resolveAuthorizedRoles(action, accessControl);\n\n const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];\n\n return (\n authorizedRoles?.[0] === '*' ||\n !!userRoles.some((role: string) => authorizedRoles.includes(role))\n );\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 async checkDynamicAccessControl(\n userId: string,\n action: string,\n resource: string,\n ) {\n const prisma = getPrismaInstance();\n\n const [userPermission, hasRolePermission] = await Promise.all([\n prisma.userPermission\n ? prisma.userPermission.findFirst({\n where: { userId, permission: { resource, action } },\n select: { effect: true },\n })\n : Promise.resolve(null),\n\n prisma.userRole.findFirst({\n where: {\n userId,\n role: {\n permissions: {\n some: { resource, action },\n },\n },\n },\n select: { id: true },\n }),\n ]);\n\n if (userPermission) return userPermission.effect === 'Allow';\n return !!hasRolePermission;\n }\n\n private extractRequestToken(\n req: ArkosRequest,\n cookie: 'arkos_access_token' = 'arkos_access_token',\n ) {\n let token: string | null = null;\n\n if (\n req?.headers?.authorization &&\n req?.headers?.authorization.startsWith('Bearer') &&\n req?.headers?.authorization.split?.(' ')?.[1]\n )\n token = req?.headers?.authorization.split(' ')[1];\n\n if (\n !token &&\n req?.cookies?.arkos_access_token !== 'no-token' &&\n req.cookies\n )\n token = req?.cookies?.[cookie];\n\n return token;\n }\n\n private extractSocketToken(socket: ArkosSocket, key: 'token' = 'token') {\n return (\n socket.handshake.auth?.[key] ||\n socket.handshake.headers?.authorization?.replace('Bearer ', '')\n );\n }\n\n async validateDecodedUser(\n decoded: AuthJwtPayload,\n action: 'logout' | 'default' = 'default',\n ): Promise<User> {\n const prisma = getPrismaInstance();\n const user = await (prisma as any).user.findUnique({\n where: { id: decoded.id },\n });\n\n if (!user)\n throw new AppError(\n 'The user belonging to this token no longer exists',\n 401,\n 'UserNoLongerExists',\n );\n\n if (\n action !== 'logout' &&\n this.userChangedPasswordAfter(user, decoded.iat!)\n )\n throw new AppError(\n 'User recently changed password! Please log in again.',\n 401,\n 'PasswordChanged',\n );\n\n return user;\n }\n\n /**\n * Processes the cookies or authoriation token and returns the user.\n *\n * @param ctx | socket\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(\n ctx: ArkosRequest | ArkosSocket,\n action: 'logout' | 'default' = 'default',\n ): Promise<User | null> {\n if (!isAuthenticationEnabled())\n throw Error(\n `Trying to call authService.getAuthenticatedUser without setting up authentication in arkos.config.${getUserFileExtension()}, see ${authenticationDocsLinks.setup}`,\n );\n\n let token: string | null = null;\n\n if ('headers' in ctx) token = this.extractRequestToken(ctx);\n else if ('join' in ctx) token = this.extractSocketToken(ctx);\n\n if (!token) return null;\n\n const decoded = await this.verifyJwtToken(token);\n ctx.accessToken = token;\n\n return this.validateDecodedUser(decoded, action);\n }\n\n /**\n * Middleware to authenticate the request by extracting and verifying the JWT token and setting `req.user`.\n *\n * Runs `authentication.hooks.authenticate` before/after the authentication logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — extracts and verifies the JWT token, sets `req.user`.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if core logic throws — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * On custom routes, hooks defined in `arkosConfig` still apply since they are baked into this method.\n *\n * @example\n * ```ts\n * // custom route - hooks still run\n * router.get(\"/custom\", authService.authenticate, handler);\n * ```\n *\n * @example\n * ```ts\n * // skip built-in auth from a before hook\n * before: (ctx) => {\n * ctx.req.user = myCustomAuth(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks}\n */\n authenticate = catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n await authHookManager.runAuthenticate(\n { context: req, done: next },\n async (req): Promise<any> => {\n if (!isAuthenticationEnabled()) return null;\n const user = (await this.getAuthenticatedUser(\n req,\n req.path.includes('logout') ? 'logout' : 'default',\n )) as User;\n if (!user) throw loginRequiredError;\n return user;\n },\n );\n },\n );\n\n /**\n * Middleware to authorize the authenticated user for a given action on a resource.\n *\n * Runs `authentication.hooks.authorize` before/after the authorization logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — checks user role/permissions against the access control rules.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if authorization fails — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * @param resource - The resource being accessed, in kebabCase (e.g. `\"product\"`, `\"cart-item\"`)\n * @param action - The action being performed (e.g. `\"View\"`, `\"Create\"`, `\"Delete\"`)\n * @param rule - Access control rules for this action. Accepts a role list, a wildcard, or a `DetailedAccessControlRule`.\n *\n * @example\n * ```ts\n * router.delete(\"/products/:id\",\n * authService.authenticate,\n * authService.authorize(\"product\", \"Delete\", [\"admin\"]),\n * handler\n * );\n * ```\n *\n * @example\n * ```ts\n * // skip built-in authorization from a before hook\n * before: (ctx) => {\n * ctx.req.user.role = myCustomRoleResolver(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks#authorize}\n * @since v1.6.0-beta\n */\n authorize(\n action: AccessAction,\n resource: string,\n rule?: string[] | DetailedAccessControlRule | '*',\n ): ArkosRequestHandler {\n const authAction = authActionService.add(action, resource, {\n [action]: rule,\n });\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n await authHookManager.runAuthorize(\n { context: req, done: next },\n authAction,\n );\n },\n );\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: User | undefined): Promise<boolean> => {\n // getArkosConfig must not be called the same time as arkos()\n const configs = getArkosConfig();\n\n if (!isUsingAuthentication())\n throw Error(\n 'Validation Error: Trying to use authService.permission without setting up authentication.',\n );\n\n if (!isAuthenticationEnabled()) return false;\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 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\n"]}