@julr/sesame 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +167 -86
  2. package/build/{authorize_controller-CUdEDNEi.js → authorize_controller-BNWhlPZQ.js} +21 -20
  3. package/build/{client_info_controller-DeIVcW8B.js → client_info_controller-BucHGx4u.js} +3 -3
  4. package/build/{client_service-B9fD3ZGe.js → client_service-BqPSlaTS.js} +1 -1
  5. package/build/commands/sesame_purge.js +3 -3
  6. package/build/configure.js +11 -2
  7. package/build/{consent_controller-DFfx7qVs.js → consent_controller-COvvkpHM.js} +28 -30
  8. package/build/index.d.ts +1 -3
  9. package/build/index.js +9 -10
  10. package/build/{introspect_controller-BzwfaUUE.js → introspect_controller-JjAAXFIV.js} +7 -7
  11. package/build/metadata_controller-BzCjyqUG.js +73 -0
  12. package/build/{oauth_access_token-BpG8sq-c.js → oauth_access_token-bsoM5KeU.js} +1 -1
  13. package/build/{oauth_client-eh0e5ql-.js → oauth_client-BIoY5jBR.js} +1 -1
  14. package/build/{oauth_error-BQPqV-MV.js → oauth_error-CnJ3L8tf.js} +17 -1
  15. package/build/providers/sesame_provider.d.ts +0 -8
  16. package/build/providers/sesame_provider.js +3 -8
  17. package/build/{register_controller-BA7uQAgt.js → register_controller-DOlN9wNl.js} +6 -6
  18. package/build/{revoke_controller-CNIgNKH3.js → revoke_controller-B281b8ZO.js} +7 -7
  19. package/build/{sesame_manager-B4tO2PLO.js → sesame_manager-CFq4VEIZ.js} +75 -15
  20. package/build/src/controllers/metadata_controller.d.ts +1 -0
  21. package/build/src/define_config.d.ts +6 -1
  22. package/build/src/guard/guard.d.ts +4 -3
  23. package/build/src/guard/main.js +6 -6
  24. package/build/src/middleware/any_scope_middleware.d.ts +15 -0
  25. package/build/src/middleware/any_scope_middleware.js +18 -0
  26. package/build/src/middleware/scope_middleware.d.ts +15 -0
  27. package/build/src/middleware/scope_middleware.js +18 -0
  28. package/build/src/models/oauth_pending_authorization_request.d.ts +29 -0
  29. package/build/src/oauth_error.d.ts +32 -0
  30. package/build/src/routes.d.ts +21 -20
  31. package/build/src/sesame_manager.d.ts +39 -8
  32. package/build/src/types.d.ts +34 -0
  33. package/build/stubs/config/sesame.stub +6 -1
  34. package/build/stubs/migrations/create_oauth_pending_authorization_requests_table.stub +32 -0
  35. package/build/{token_controller-C9wh813f.js → token_controller-ll9sjcvn.js} +12 -11
  36. package/build/{token_service-Czz9v5GI.js → token_service-fhoA4slP.js} +2 -1
  37. package/build/{user_provider-B3rXEUT3.js → user_provider-DXAOfv8-.js} +3 -3
  38. package/package.json +7 -2
  39. package/build/main-kn40V-hF.js +0 -2
  40. package/build/metadata_controller-BSRRElQX.js +0 -51
  41. package/build/rolldown-runtime-BASaM9lw.js +0 -12
  42. package/build/routes-D6QCu0Pz.js +0 -43
  43. /package/build/{decorate-2_8Ex77k.js → decorate-BKZEjPRg.js} +0 -0
@@ -1,8 +1,10 @@
1
- import type { ResolvedSesameConfig } from './types.ts';
1
+ import type { Router } from '@adonisjs/core/http';
2
+ import type { ResolvedSesameConfig, Scope } from './types.ts';
2
3
  export interface PurgeResult {
3
4
  accessTokens: number;
4
5
  refreshTokens: number;
5
6
  authorizationCodes: number;
7
+ pendingRequests: number;
6
8
  }
7
9
  /**
8
10
  * Central manager for the Sésame OAuth 2.1 server.
@@ -19,7 +21,7 @@ export declare class SesameManager {
19
21
  *
20
22
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3
21
23
  */
22
- hasScope(scope: string): boolean;
24
+ hasScope(scope: Scope): boolean;
23
25
  /**
24
26
  * Return the list of scopes that are not registered in the
25
27
  * server configuration. When no scopes are configured, all
@@ -30,7 +32,7 @@ export declare class SesameManager {
30
32
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3
31
33
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1
32
34
  */
33
- validateScopes(scopes: string[]): string[];
35
+ validateScopes(scopes: Scope[]): string[];
34
36
  /**
35
37
  * Check if a grant type is enabled in the server configuration.
36
38
  */
@@ -50,8 +52,6 @@ export declare class SesameManager {
50
52
  * Returns the total number of deleted records. Expired tokens are
51
53
  * retained for `retentionHours` (default 168 = 7 days) to allow
52
54
  * for debugging and audit trails.
53
- *
54
- * Inspired by Laravel Passport's `passport:purge` command.
55
55
  */
56
56
  purgeTokens(options?: {
57
57
  revokedOnly?: boolean;
@@ -59,8 +59,39 @@ export declare class SesameManager {
59
59
  retentionHours?: number;
60
60
  }): Promise<PurgeResult>;
61
61
  /**
62
- * Parse a duration string like '1h', '30m', '10d' into seconds.
63
- * Supported units: `s` (seconds), `m` (minutes), `h` (hours), `d` (days).
62
+ * Register OAuth 2.1 endpoint routes (token, authorize, consent, etc.).
63
+ *
64
+ * Paths are relative — wrap the call in a `router.group().prefix()`
65
+ * to control the mount point.
66
+ *
67
+ * Do not apply session-auth middleware to the entire OAuth group.
68
+ * Endpoints like `/token`, `/introspect`, `/revoke`, and `/register`
69
+ * must stay callable without a browser session.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * router.group(() => {
74
+ * sesame.registerRoutes(router)
75
+ * }).prefix('/oauth')
76
+ * ```
77
+ */
78
+ registerRoutes(router: Router): void;
79
+ /**
80
+ * Register well-known discovery routes at the root level.
81
+ *
82
+ * Must be called outside any prefix group so endpoints
83
+ * remain at `/.well-known/...`.
84
+ */
85
+ registerWellKnownRoutes(router: Router): void;
86
+ /**
87
+ * Register a `/.well-known/oauth-protected-resource` endpoint
88
+ * for a specific resource path (RFC 9728). Useful for MCP
89
+ * servers that need per-resource discovery.
90
+ *
91
+ * @see https://datatracker.ietf.org/doc/html/rfc9728
64
92
  */
65
- parseTtl(ttl: string): number;
93
+ registerProtectedResource(router: Router, options: {
94
+ resource: string;
95
+ scopes?: Scope[];
96
+ }): void;
66
97
  }
@@ -1,4 +1,31 @@
1
1
  import type { HttpContext } from '@adonisjs/core/http';
2
+ /**
3
+ * Augment this interface via module augmentation to enable
4
+ * type-safe scope names across the application.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * declare module '@julr/sesame/types' {
9
+ * interface SesameScopes extends InferScopes<typeof sesameConfig> {}
10
+ * }
11
+ * ```
12
+ */
13
+ export interface SesameScopes {
14
+ }
15
+ /**
16
+ * Resolved scope type. When `SesameScopes` is augmented, narrows
17
+ * to the declared scope keys. Otherwise falls back to `string`.
18
+ */
19
+ export type Scope = keyof SesameScopes extends never ? string : keyof SesameScopes & string;
20
+ /**
21
+ * Extract scope keys from a config object returned by `defineConfig`.
22
+ * Use with `declare module` to propagate type-safe scopes globally.
23
+ */
24
+ export type InferScopes<T extends {
25
+ scopes: Record<string, string>;
26
+ }> = {
27
+ [K in keyof T['scopes'] & string]: true;
28
+ };
2
29
  /**
3
30
  * Supported grant types for v1 (MCP-focused).
4
31
  *
@@ -55,6 +82,12 @@ export interface SesameConfig {
55
82
  * Defaults to '10m'.
56
83
  */
57
84
  authorizationCodeTtl?: string;
85
+ /**
86
+ * Pending authorization request TTL as a string duration.
87
+ * Controls how long a user has to approve/deny a consent screen.
88
+ * Defaults to `authorizationCodeTtl` (typically '10m').
89
+ */
90
+ authorizationRequestTtl?: string;
58
91
  /**
59
92
  * Route or URL where unauthenticated users are redirected
60
93
  * to log in during the authorization flow. Can be a string
@@ -94,6 +127,7 @@ export interface ResolvedSesameConfig {
94
127
  accessTokenTtl: string;
95
128
  refreshTokenTtl: string;
96
129
  authorizationCodeTtl: string;
130
+ authorizationRequestTtl: string;
97
131
  loginPage: string | ((ctx: HttpContext, params: URLSearchParams) => string);
98
132
  consentPage: string | ((ctx: HttpContext, params: URLSearchParams) => string);
99
133
  allowDynamicRegistration: boolean;
@@ -1,7 +1,8 @@
1
1
  {{{
2
- exports: { defineConfig: 'import { defineConfig } from \'@adonisjs/sesame\'' }
2
+ exports: { defineConfig: 'import { defineConfig } from \'@julr/sesame\'' }
3
3
  }}}
4
4
  import env from '#start/env'
5
+ import type { InferScopes } from '@julr/sesame/types'
5
6
 
6
7
  const sesameConfig = defineConfig({
7
8
  issuer: env.get('APP_URL'),
@@ -28,3 +29,7 @@ const sesameConfig = defineConfig({
28
29
  })
29
30
 
30
31
  export default sesameConfig
32
+
33
+ declare module '@julr/sesame/types' {
34
+ interface SesameScopes extends InferScopes<typeof sesameConfig> {}
35
+ }
@@ -0,0 +1,32 @@
1
+ {{{
2
+ exports: { migration: "import { BaseSchema } from '@adonisjs/lucid/schema'" }
3
+ }}}
4
+
5
+ export default class extends BaseSchema {
6
+ protected tableName = 'oauth_pending_authorization_requests'
7
+
8
+ async up() {
9
+ this.schema.createTable(this.tableName, (table) => {
10
+ table.uuid('id').primary()
11
+ table.string('token').notNullable().index()
12
+ table
13
+ .string('client_id')
14
+ .notNullable()
15
+ .references('client_id')
16
+ .inTable('oauth_clients')
17
+ .onDelete('CASCADE')
18
+ table.string('user_id').notNullable()
19
+ table.json('scopes').notNullable()
20
+ table.text('redirect_uri').notNullable()
21
+ table.string('state').nullable()
22
+ table.string('code_challenge').nullable()
23
+ table.string('code_challenge_method').nullable()
24
+ table.timestamp('expires_at').notNullable()
25
+ table.timestamp('created_at').notNullable()
26
+ })
27
+ }
28
+
29
+ async down() {
30
+ this.schema.dropTable(this.tableName)
31
+ }
32
+ }
@@ -1,12 +1,13 @@
1
- import "./decorate-2_8Ex77k.js";
2
- import { t as OAuthAccessToken } from "./oauth_access_token-BpG8sq-c.js";
3
- import { a as OAuthRefreshToken, i as OAuthAuthorizationCode, t as SesameManager } from "./sesame_manager-B4tO2PLO.js";
4
- import { a as E_INVALID_REQUEST, i as E_INVALID_GRANT, l as E_UNSUPPORTED_GRANT_TYPE, n as E_INVALID_CLIENT, o as E_INVALID_SCOPE } from "./oauth_error-BQPqV-MV.js";
5
- import { t as OAuthClient } from "./oauth_client-eh0e5ql-.js";
6
- import { t as TokenService } from "./token_service-Czz9v5GI.js";
7
- import { t as ClientService } from "./client_service-B9fD3ZGe.js";
1
+ import { a as OAuthAuthorizationCode, o as OAuthRefreshToken, t as SesameManager } from "./sesame_manager-CFq4VEIZ.js";
2
+ import "./decorate-BKZEjPRg.js";
3
+ import { t as OAuthAccessToken } from "./oauth_access_token-bsoM5KeU.js";
4
+ import { a as E_INVALID_GRANT, o as E_INVALID_REQUEST, r as E_INVALID_CLIENT, s as E_INVALID_SCOPE, u as E_UNSUPPORTED_GRANT_TYPE } from "./oauth_error-CnJ3L8tf.js";
5
+ import { t as OAuthClient } from "./oauth_client-BIoY5jBR.js";
6
+ import { t as TokenService } from "./token_service-fhoA4slP.js";
7
+ import { t as ClientService } from "./client_service-BqPSlaTS.js";
8
8
  import { DateTime } from "luxon";
9
9
  import { createHash } from "node:crypto";
10
+ import string from "@adonisjs/core/helpers/string";
10
11
  import vine from "@vinejs/vine";
11
12
  const codeVerifierValidator = vine.create({ code_verifier: vine.string().minLength(43).maxLength(128).regex(/^[A-Za-z0-9\-._~]+$/) });
12
13
  async function handleAuthorizationCodeGrant(ctx, manager) {
@@ -59,7 +60,7 @@ async function handleAuthorizationCodeGrant(ctx, manager) {
59
60
  let refreshTokenRaw;
60
61
  if (authCode.scopes.includes("offline_access")) {
61
62
  const { raw, hash } = tokenService.createRefreshToken();
62
- const refreshTtl = manager.parseTtl(manager.config.refreshTokenTtl);
63
+ const refreshTtl = string.seconds.parse(manager.config.refreshTokenTtl);
63
64
  await OAuthRefreshToken.create({
64
65
  id: crypto.randomUUID(),
65
66
  token: hash,
@@ -74,7 +75,7 @@ async function handleAuthorizationCodeGrant(ctx, manager) {
74
75
  return {
75
76
  access_token: accessTokenRaw,
76
77
  token_type: "Bearer",
77
- expires_in: manager.parseTtl(manager.config.accessTokenTtl),
78
+ expires_in: string.seconds.parse(manager.config.accessTokenTtl),
78
79
  scope: authCode.scopes.join(" "),
79
80
  ...refreshTokenRaw ? { refresh_token: refreshTokenRaw } : {}
80
81
  };
@@ -132,7 +133,7 @@ async function handleRefreshTokenGrant(ctx, manager) {
132
133
  expiresAt: DateTime.fromJSDate(expiresAt)
133
134
  });
134
135
  const { raw: newRefreshTokenRaw, hash: newRefreshTokenHash } = tokenService.createRefreshToken();
135
- const refreshTtl = manager.parseTtl(manager.config.refreshTokenTtl);
136
+ const refreshTtl = string.seconds.parse(manager.config.refreshTokenTtl);
136
137
  await OAuthRefreshToken.create({
137
138
  id: crypto.randomUUID(),
138
139
  token: newRefreshTokenHash,
@@ -145,7 +146,7 @@ async function handleRefreshTokenGrant(ctx, manager) {
145
146
  return {
146
147
  access_token: accessTokenRaw,
147
148
  token_type: "Bearer",
148
- expires_in: manager.parseTtl(manager.config.accessTokenTtl),
149
+ expires_in: string.seconds.parse(manager.config.accessTokenTtl),
149
150
  scope: scopes.join(" "),
150
151
  refresh_token: newRefreshTokenRaw
151
152
  };
@@ -1,4 +1,5 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
+ import string from "@adonisjs/core/helpers/string";
2
3
  var TokenService = class {
3
4
  #manager;
4
5
  constructor(manager) {
@@ -6,7 +7,7 @@ var TokenService = class {
6
7
  }
7
8
  createAccessToken() {
8
9
  const raw = this.generateOpaqueToken();
9
- const ttlSeconds = this.#manager.parseTtl(this.#manager.config.accessTokenTtl);
10
+ const ttlSeconds = string.seconds.parse(this.#manager.config.accessTokenTtl);
10
11
  return {
11
12
  raw,
12
13
  hash: this.hashToken(raw),
@@ -1,6 +1,6 @@
1
- import { t as OAuthAccessToken } from "./oauth_access_token-BpG8sq-c.js";
2
- import { t as OAuthClient } from "./oauth_client-eh0e5ql-.js";
3
- import { t as TokenService } from "./token_service-Czz9v5GI.js";
1
+ import { t as OAuthAccessToken } from "./oauth_access_token-bsoM5KeU.js";
2
+ import { t as OAuthClient } from "./oauth_client-BIoY5jBR.js";
3
+ import { t as TokenService } from "./token_service-fhoA4slP.js";
4
4
  import { DateTime } from "luxon";
5
5
  import { RuntimeException } from "@adonisjs/core/exceptions";
6
6
  import { errors } from "@adonisjs/auth";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@julr/sesame",
3
3
  "description": "OAuth 2.1 + OIDC server for AdonisJS",
4
- "version": "0.1.0",
4
+ "version": "0.2.1",
5
5
  "engines": {
6
6
  "node": ">=24.0.0"
7
7
  },
@@ -18,6 +18,8 @@
18
18
  "./types": "./build/src/types.js",
19
19
  "./sesame_provider": "./build/providers/sesame_provider.js",
20
20
  "./guard": "./build/src/guard/main.js",
21
+ "./scope_middleware": "./build/src/middleware/scope_middleware.js",
22
+ "./any_scope_middleware": "./build/src/middleware/any_scope_middleware.js",
21
23
  "./commands/*": "./build/commands/*.js",
22
24
  "./commands": "./build/commands/main.js"
23
25
  },
@@ -57,6 +59,7 @@
57
59
  "@adonisjs/prettier-config": "^1.4.5",
58
60
  "@adonisjs/tsconfig": "^2.0.0",
59
61
  "@japa/assert": "^4.2.0",
62
+ "@japa/expect-type": "^2.0.4",
60
63
  "@japa/runner": "^5.3.0",
61
64
  "@poppinss/ts-exec": "^1.4.4",
62
65
  "@release-it/conventional-changelog": "^10.0.5",
@@ -94,7 +97,9 @@
94
97
  "./configure.ts",
95
98
  "./providers/sesame_provider.ts",
96
99
  "./src/guard/main.ts",
97
- "./commands/sesame_purge.ts"
100
+ "./commands/sesame_purge.ts",
101
+ "./src/middleware/scope_middleware.ts",
102
+ "./src/middleware/any_scope_middleware.ts"
98
103
  ],
99
104
  "outDir": "./build",
100
105
  "clean": true,
@@ -1,2 +0,0 @@
1
- const stubsRoot = import.meta.dirname;
2
- export { stubsRoot as t };
@@ -1,51 +0,0 @@
1
- import "./decorate-2_8Ex77k.js";
2
- import "./oauth_access_token-BpG8sq-c.js";
3
- import { t as SesameManager } from "./sesame_manager-B4tO2PLO.js";
4
- var MetadataController = class {
5
- async authServer(ctx) {
6
- const manager = await ctx.containerResolver.make(SesameManager);
7
- const issuer = manager.config.issuer;
8
- ctx.response.header("Cache-Control", "public, max-age=15, stale-while-revalidate=15, stale-if-error=86400");
9
- return {
10
- issuer,
11
- authorization_endpoint: `${issuer}/oauth/authorize`,
12
- token_endpoint: `${issuer}/oauth/token`,
13
- registration_endpoint: manager.config.allowDynamicRegistration ? `${issuer}/oauth/register` : void 0,
14
- introspection_endpoint: `${issuer}/oauth/introspect`,
15
- revocation_endpoint: `${issuer}/oauth/revoke`,
16
- response_types_supported: ["code"],
17
- response_modes_supported: ["query"],
18
- grant_types_supported: manager.config.grantTypes,
19
- token_endpoint_auth_methods_supported: [
20
- "none",
21
- "client_secret_basic",
22
- "client_secret_post"
23
- ],
24
- introspection_endpoint_auth_methods_supported: ["client_secret_basic", "client_secret_post"],
25
- revocation_endpoint_auth_methods_supported: ["client_secret_basic", "client_secret_post"],
26
- code_challenge_methods_supported: ["S256"],
27
- authorization_response_iss_parameter_supported: true
28
- };
29
- }
30
- async oidc(ctx) {
31
- const base = await this.authServer(ctx);
32
- const manager = await ctx.containerResolver.make(SesameManager);
33
- return {
34
- ...base,
35
- subject_types_supported: ["public"],
36
- scopes_supported: Object.keys(manager.config.scopes)
37
- };
38
- }
39
- async protectedResource(ctx) {
40
- const manager = await ctx.containerResolver.make(SesameManager);
41
- const issuer = manager.config.issuer;
42
- ctx.response.header("Cache-Control", "public, max-age=15, stale-while-revalidate=15, stale-if-error=86400");
43
- return {
44
- resource: issuer,
45
- authorization_servers: [issuer],
46
- scopes_supported: Object.keys(manager.config.scopes),
47
- bearer_methods_supported: ["header"]
48
- };
49
- }
50
- };
51
- export { MetadataController as default };
@@ -1,12 +0,0 @@
1
- import "node:module";
2
- var __defProp = Object.defineProperty;
3
- var __exportAll = (all, no_symbols) => {
4
- let target = {};
5
- for (var name in all) __defProp(target, name, {
6
- get: all[name],
7
- enumerable: true
8
- });
9
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
- return target;
11
- };
12
- export { __exportAll as t };
@@ -1,43 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-BASaM9lw.js";
2
- var routes_exports = /* @__PURE__ */ __exportAll({
3
- registerProtectedResource: () => registerProtectedResource,
4
- registerRoutes: () => registerRoutes
5
- });
6
- const controllers = {
7
- token: () => import("./token_controller-C9wh813f.js"),
8
- authorize: () => import("./authorize_controller-CUdEDNEi.js"),
9
- consent: () => import("./consent_controller-DFfx7qVs.js"),
10
- introspect: () => import("./introspect_controller-BzwfaUUE.js"),
11
- revoke: () => import("./revoke_controller-CNIgNKH3.js"),
12
- register: () => import("./register_controller-BA7uQAgt.js"),
13
- metadata: () => import("./metadata_controller-BSRRElQX.js"),
14
- clientInfo: () => import("./client_info_controller-DeIVcW8B.js")
15
- };
16
- function registerRoutes(router) {
17
- router.post("/oauth/token", [controllers.token]).as("sesame.token");
18
- router.get("/oauth/authorize", [controllers.authorize]).as("sesame.authorize");
19
- router.post("/oauth/consent", [controllers.consent]).as("sesame.consent");
20
- router.get("/oauth/client-info", [controllers.clientInfo]).as("sesame.clientInfo");
21
- router.post("/oauth/introspect", [controllers.introspect]).as("sesame.introspect");
22
- router.post("/oauth/revoke", [controllers.revoke]).as("sesame.revoke");
23
- router.post("/oauth/register", [controllers.register]).as("sesame.register");
24
- router.get("/.well-known/oauth-authorization-server", [controllers.metadata, "authServer"]).as("sesame.metadata.authServer");
25
- router.get("/.well-known/openid-configuration", [controllers.metadata, "oidc"]).as("sesame.metadata.oidc");
26
- router.get("/.well-known/oauth-protected-resource", [controllers.metadata, "protectedResource"]).as("sesame.metadata.protectedResource");
27
- }
28
- function registerProtectedResource(router, options) {
29
- const wellKnownPath = `/.well-known/oauth-protected-resource${options.resource}`;
30
- router.get(wellKnownPath, async (ctx) => {
31
- const { SesameManager } = await import("./sesame_manager-B4tO2PLO.js").then((n) => n.n);
32
- const manager = await ctx.containerResolver.make(SesameManager);
33
- const issuer = manager.config.issuer;
34
- ctx.response.header("Cache-Control", "public, max-age=15, stale-while-revalidate=15, stale-if-error=86400");
35
- return {
36
- resource: `${issuer}${options.resource}`,
37
- authorization_servers: [issuer],
38
- scopes_supported: options.scopes ?? Object.keys(manager.config.scopes),
39
- bearer_methods_supported: ["header"]
40
- };
41
- });
42
- }
43
- export { registerRoutes as n, routes_exports as r, registerProtectedResource as t };