@carlonicora/nextjs-jsonapi 1.24.3 → 1.25.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 (76) hide show
  1. package/dist/{BlockNoteEditor-OFSTXGZX.js → BlockNoteEditor-7WAWEZVW.js} +13 -13
  2. package/dist/{BlockNoteEditor-OFSTXGZX.js.map → BlockNoteEditor-7WAWEZVW.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-TJNLCNIP.mjs → BlockNoteEditor-UNVKGZ2G.mjs} +3 -3
  4. package/dist/billing/index.js +342 -342
  5. package/dist/billing/index.mjs +2 -2
  6. package/dist/{chunk-H5JZ5E7M.mjs → chunk-6BDOZDZ3.mjs} +1247 -54
  7. package/dist/chunk-6BDOZDZ3.mjs.map +1 -0
  8. package/dist/{chunk-EJALOG7L.js → chunk-JI6BDV7L.js} +1598 -405
  9. package/dist/chunk-JI6BDV7L.js.map +1 -0
  10. package/dist/{chunk-5U4NJJOF.mjs → chunk-LNBT2YPZ.mjs} +289 -2
  11. package/dist/chunk-LNBT2YPZ.mjs.map +1 -0
  12. package/dist/{chunk-NQVPCNRS.js → chunk-O3LLMGP7.js} +290 -3
  13. package/dist/chunk-O3LLMGP7.js.map +1 -0
  14. package/dist/client/index.d.mts +96 -1
  15. package/dist/client/index.d.ts +96 -1
  16. package/dist/client/index.js +9 -3
  17. package/dist/client/index.js.map +1 -1
  18. package/dist/client/index.mjs +8 -2
  19. package/dist/components/index.d.mts +225 -1
  20. package/dist/components/index.d.ts +225 -1
  21. package/dist/components/index.js +25 -3
  22. package/dist/components/index.js.map +1 -1
  23. package/dist/components/index.mjs +24 -2
  24. package/dist/contexts/index.js +3 -3
  25. package/dist/contexts/index.mjs +2 -2
  26. package/dist/core/index.d.mts +108 -1
  27. package/dist/core/index.d.ts +108 -1
  28. package/dist/core/index.js +14 -2
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/core/index.mjs +13 -1
  31. package/dist/index.d.mts +2 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.js +14 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +13 -1
  36. package/dist/oauth.interface-DsZ5ecSX.d.mts +119 -0
  37. package/dist/oauth.interface-vL7za9Bz.d.ts +119 -0
  38. package/dist/server/index.js +3 -3
  39. package/dist/server/index.mjs +1 -1
  40. package/package.json +3 -2
  41. package/src/client/index.ts +1 -0
  42. package/src/components/index.ts +1 -0
  43. package/src/core/index.ts +3 -0
  44. package/src/core/registry/ModuleRegistry.ts +2 -0
  45. package/src/features/index.ts +1 -0
  46. package/src/features/oauth/atoms/index.ts +1 -0
  47. package/src/features/oauth/atoms/oauth.atoms.ts +131 -0
  48. package/src/features/oauth/components/OAuthClientCard.tsx +105 -0
  49. package/src/features/oauth/components/OAuthClientDetail.tsx +269 -0
  50. package/src/features/oauth/components/OAuthClientForm.tsx +212 -0
  51. package/src/features/oauth/components/OAuthClientList.tsx +127 -0
  52. package/src/features/oauth/components/OAuthClientSecretDisplay.tsx +127 -0
  53. package/src/features/oauth/components/OAuthRedirectUriInput.tsx +152 -0
  54. package/src/features/oauth/components/OAuthScopeSelector.tsx +123 -0
  55. package/src/features/oauth/components/consent/OAuthConsentActions.tsx +41 -0
  56. package/src/features/oauth/components/consent/OAuthConsentHeader.tsx +51 -0
  57. package/src/features/oauth/components/consent/OAuthConsentScreen.tsx +142 -0
  58. package/src/features/oauth/components/consent/OAuthScopeList.tsx +72 -0
  59. package/src/features/oauth/components/consent/index.ts +4 -0
  60. package/src/features/oauth/components/index.ts +8 -0
  61. package/src/features/oauth/data/index.ts +2 -0
  62. package/src/features/oauth/data/oauth.service.ts +191 -0
  63. package/src/features/oauth/data/oauth.ts +87 -0
  64. package/src/features/oauth/hooks/index.ts +3 -0
  65. package/src/features/oauth/hooks/useOAuthClient.ts +161 -0
  66. package/src/features/oauth/hooks/useOAuthClients.ts +111 -0
  67. package/src/features/oauth/hooks/useOAuthConsent.ts +125 -0
  68. package/src/features/oauth/index.ts +6 -0
  69. package/src/features/oauth/interfaces/index.ts +1 -0
  70. package/src/features/oauth/interfaces/oauth.interface.ts +175 -0
  71. package/src/features/oauth/oauth.module.ts +9 -0
  72. package/dist/chunk-5U4NJJOF.mjs.map +0 -1
  73. package/dist/chunk-EJALOG7L.js.map +0 -1
  74. package/dist/chunk-H5JZ5E7M.mjs.map +0 -1
  75. package/dist/chunk-NQVPCNRS.js.map +0 -1
  76. /package/dist/{BlockNoteEditor-TJNLCNIP.mjs.map → BlockNoteEditor-UNVKGZ2G.mjs.map} +0 -0
@@ -0,0 +1,125 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useState } from "react";
4
+ import { OAuthConsentInfo, OAuthConsentRequest } from "../interfaces/oauth.interface";
5
+ import { OAuthService } from "../data/oauth.service";
6
+
7
+ export interface UseOAuthConsentReturn {
8
+ /** Client and scope info for consent display */
9
+ clientInfo: OAuthConsentInfo | null;
10
+ /** Whether consent info is being loaded */
11
+ isLoading: boolean;
12
+ /** Error from consent flow */
13
+ error: Error | null;
14
+ /** Approve the authorization request */
15
+ approve: () => Promise<void>;
16
+ /** Deny the authorization request */
17
+ deny: () => Promise<void>;
18
+ /** Whether approve/deny is in progress */
19
+ isSubmitting: boolean;
20
+ }
21
+
22
+ /**
23
+ * Hook for managing the OAuth consent flow
24
+ *
25
+ * @param params - OAuth authorization parameters from URL
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * const { clientInfo, isLoading, approve, deny } = useOAuthConsent({
30
+ * clientId: searchParams.client_id,
31
+ * redirectUri: searchParams.redirect_uri,
32
+ * scope: searchParams.scope,
33
+ * state: searchParams.state,
34
+ * });
35
+ *
36
+ * // Render consent screen with clientInfo
37
+ * // On button click: approve() or deny()
38
+ * ```
39
+ */
40
+ export function useOAuthConsent(params: OAuthConsentRequest): UseOAuthConsentReturn {
41
+ const [clientInfo, setClientInfo] = useState<OAuthConsentInfo | null>(null);
42
+ const [isLoading, setIsLoading] = useState(true);
43
+ const [error, setError] = useState<Error | null>(null);
44
+ const [isSubmitting, setIsSubmitting] = useState(false);
45
+
46
+ // Fetch client info on mount
47
+ useEffect(() => {
48
+ const fetchInfo = async () => {
49
+ if (!params.clientId || !params.redirectUri || !params.scope) {
50
+ setError(new Error("Missing required authorization parameters"));
51
+ setIsLoading(false);
52
+ return;
53
+ }
54
+
55
+ setIsLoading(true);
56
+ setError(null);
57
+
58
+ try {
59
+ const info = await OAuthService.getAuthorizationInfo(params);
60
+ setClientInfo(info);
61
+ } catch (err) {
62
+ console.error("[useOAuthConsent] Failed to fetch authorization info:", err);
63
+ setError(err instanceof Error ? err : new Error("Failed to load authorization info"));
64
+ } finally {
65
+ setIsLoading(false);
66
+ }
67
+ };
68
+
69
+ fetchInfo();
70
+ }, [
71
+ params.clientId,
72
+ params.redirectUri,
73
+ params.scope,
74
+ params.state,
75
+ params.codeChallenge,
76
+ params.codeChallengeMethod,
77
+ ]);
78
+
79
+ const approve = useCallback(async (): Promise<void> => {
80
+ setIsSubmitting(true);
81
+ setError(null);
82
+
83
+ try {
84
+ const result = await OAuthService.approveAuthorization(params);
85
+
86
+ // Redirect to client with authorization code
87
+ if (result.redirectUrl) {
88
+ window.location.href = result.redirectUrl;
89
+ }
90
+ } catch (err) {
91
+ console.error("[useOAuthConsent] Failed to approve authorization:", err);
92
+ setError(err instanceof Error ? err : new Error("Failed to approve authorization"));
93
+ setIsSubmitting(false);
94
+ }
95
+ // Note: Don't set isSubmitting to false on success - we're redirecting
96
+ }, [params]);
97
+
98
+ const deny = useCallback(async (): Promise<void> => {
99
+ setIsSubmitting(true);
100
+ setError(null);
101
+
102
+ try {
103
+ const result = await OAuthService.denyAuthorization(params);
104
+
105
+ // Redirect to client with error
106
+ if (result.redirectUrl) {
107
+ window.location.href = result.redirectUrl;
108
+ }
109
+ } catch (err) {
110
+ console.error("[useOAuthConsent] Failed to deny authorization:", err);
111
+ setError(err instanceof Error ? err : new Error("Failed to deny authorization"));
112
+ setIsSubmitting(false);
113
+ }
114
+ // Note: Don't set isSubmitting to false on success - we're redirecting
115
+ }, [params]);
116
+
117
+ return {
118
+ clientInfo,
119
+ isLoading,
120
+ error,
121
+ approve,
122
+ deny,
123
+ isSubmitting,
124
+ };
125
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./oauth.module";
2
+ export * from "./interfaces";
3
+ export * from "./data";
4
+ export * from "./atoms";
5
+ export * from "./hooks";
6
+ export * from "./components";
@@ -0,0 +1 @@
1
+ export * from "./oauth.interface";
@@ -0,0 +1,175 @@
1
+ import { ApiDataInterface } from "../../../core";
2
+
3
+ /**
4
+ * OAuth client application interface
5
+ * Represents a registered OAuth application that can request access tokens
6
+ */
7
+ export interface OAuthClientInterface extends ApiDataInterface {
8
+ /** The public client identifier (UUID format) */
9
+ get clientId(): string;
10
+ /** Human-readable application name */
11
+ get name(): string;
12
+ /** Optional description of the application */
13
+ get description(): string | undefined;
14
+ /** Array of allowed redirect URIs (exact match validation) */
15
+ get redirectUris(): string[];
16
+ /** Array of scopes this client can request */
17
+ get allowedScopes(): string[];
18
+ /** Supported grant types (authorization_code, client_credentials, refresh_token) */
19
+ get allowedGrantTypes(): string[];
20
+ /** True for server-side apps (can keep secret secure), false for mobile/desktop apps */
21
+ get isConfidential(): boolean;
22
+ /** Whether the client is currently active */
23
+ get isActive(): boolean;
24
+ /** When the client was created */
25
+ get createdAt(): Date;
26
+ /** When the client was last updated */
27
+ get updatedAt(): Date;
28
+ }
29
+
30
+ /**
31
+ * Input type for OAuth client CRUD operations
32
+ */
33
+ export type OAuthClientInput = {
34
+ id?: string;
35
+ name?: string;
36
+ description?: string;
37
+ redirectUris?: string[];
38
+ allowedScopes?: string[];
39
+ allowedGrantTypes?: string[];
40
+ isConfidential?: boolean;
41
+ isActive?: boolean;
42
+ };
43
+
44
+ /**
45
+ * Request body for creating a new OAuth client
46
+ */
47
+ export interface OAuthClientCreateRequest {
48
+ /** Required: Human-readable application name */
49
+ name: string;
50
+ /** Optional: Description of the application */
51
+ description?: string;
52
+ /** Required: At least one redirect URI */
53
+ redirectUris: string[];
54
+ /** Required: Array of scopes the client needs */
55
+ allowedScopes: string[];
56
+ /** Optional: Grant types (defaults to authorization_code + refresh_token) */
57
+ allowedGrantTypes?: string[];
58
+ /** Required: Whether this is a confidential client */
59
+ isConfidential: boolean;
60
+ }
61
+
62
+ /**
63
+ * Response when creating a client (includes one-time secret)
64
+ */
65
+ export interface OAuthClientCreateResponse {
66
+ client: OAuthClientInterface;
67
+ /** Only returned on creation - must be saved immediately */
68
+ clientSecret?: string;
69
+ }
70
+
71
+ /**
72
+ * Parameters for the OAuth authorization consent flow
73
+ * Passed via URL query parameters to the consent page
74
+ */
75
+ export interface OAuthConsentRequest {
76
+ /** The client_id requesting authorization */
77
+ clientId: string;
78
+ /** Where to redirect after authorization */
79
+ redirectUri: string;
80
+ /** Space-separated list of requested scopes */
81
+ scope: string;
82
+ /** CSRF protection token (passed back on redirect) */
83
+ state?: string;
84
+ /** PKCE code challenge (required for public clients) */
85
+ codeChallenge?: string;
86
+ /** PKCE method: 'S256' (recommended) or 'plain' */
87
+ codeChallengeMethod?: string;
88
+ }
89
+
90
+ /**
91
+ * Scope information for display in consent screen
92
+ */
93
+ export interface OAuthScopeInfo {
94
+ /** The scope identifier (e.g., 'photographs:read') */
95
+ scope: string;
96
+ /** Human-readable scope name */
97
+ name: string;
98
+ /** Description of what this scope allows */
99
+ description: string;
100
+ /** Optional icon identifier */
101
+ icon?: string;
102
+ }
103
+
104
+ /**
105
+ * Client info returned for consent screen display
106
+ */
107
+ export interface OAuthConsentInfo {
108
+ client: OAuthClientInterface;
109
+ scopes: OAuthScopeInfo[];
110
+ }
111
+
112
+ /**
113
+ * Default scope display configuration
114
+ * Maps scope identifiers to human-readable info
115
+ */
116
+ export const OAUTH_SCOPE_DISPLAY: Record<string, OAuthScopeInfo> = {
117
+ read: {
118
+ scope: "read",
119
+ name: "Read Access",
120
+ description: "Read access to your data",
121
+ icon: "eye",
122
+ },
123
+ write: {
124
+ scope: "write",
125
+ name: "Write Access",
126
+ description: "Write access to your data",
127
+ icon: "pencil",
128
+ },
129
+ "photographs:read": {
130
+ scope: "photographs:read",
131
+ name: "View Photographs",
132
+ description: "Access and download your photo library",
133
+ icon: "image",
134
+ },
135
+ "photographs:write": {
136
+ scope: "photographs:write",
137
+ name: "Upload Photographs",
138
+ description: "Add new photos to your rolls",
139
+ icon: "upload",
140
+ },
141
+ "rolls:read": {
142
+ scope: "rolls:read",
143
+ name: "View Rolls",
144
+ description: "See your film rolls and collections",
145
+ icon: "film",
146
+ },
147
+ "rolls:write": {
148
+ scope: "rolls:write",
149
+ name: "Manage Rolls",
150
+ description: "Create and modify film rolls",
151
+ icon: "folder-plus",
152
+ },
153
+ profile: {
154
+ scope: "profile",
155
+ name: "View Profile",
156
+ description: "Access your name and email",
157
+ icon: "user",
158
+ },
159
+ admin: {
160
+ scope: "admin",
161
+ name: "Administrative Access",
162
+ description: "Full administrative access to your account",
163
+ icon: "shield",
164
+ },
165
+ };
166
+
167
+ /**
168
+ * Available scopes list for the scope selector
169
+ */
170
+ export const AVAILABLE_OAUTH_SCOPES: OAuthScopeInfo[] = Object.values(OAUTH_SCOPE_DISPLAY);
171
+
172
+ /**
173
+ * Default grant types for new clients
174
+ */
175
+ export const DEFAULT_GRANT_TYPES = ["authorization_code", "refresh_token"];
@@ -0,0 +1,9 @@
1
+ import { ModuleFactory } from "../../permissions";
2
+ import { OAuthClient } from "./data/oauth";
3
+
4
+ export const OAuthModule = (factory: ModuleFactory) =>
5
+ factory({
6
+ pageUrl: "/oauth",
7
+ name: "oauth-clients",
8
+ model: OAuthClient,
9
+ });