@neog-cloud/neog-api-client 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/auth/AuthProvider.d.ts +14 -0
- package/dist/auth/options.d.ts +27 -0
- package/dist/auth/storage.d.ts +13 -0
- package/dist/auth/types.d.ts +37 -0
- package/dist/auth/useAuth.d.ts +2 -0
- package/dist/client/neogClient.d.ts +29 -0
- package/dist/client/types.d.ts +40 -0
- package/dist/index.cjs +1784 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.mjs +1782 -0
- package/dist/index.mjs.map +1 -0
- package/dist/utils/errors.d.ts +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Neog Auth Client
|
|
2
|
+
|
|
3
|
+
Pacote TypeScript reutilizável para autenticação e consumo da API da plataforma neog.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @neog-cloud/neog-api-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuração
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createNeogAuth } from "@neog-cloud/neog-api-client";
|
|
15
|
+
|
|
16
|
+
const { AuthProvider, useAuth, createNeogClient } = createNeogAuth({
|
|
17
|
+
baseUrl: "https://api_neog",
|
|
18
|
+
authBaseUrl: "https://iam_neog",
|
|
19
|
+
authRealm: "__REALM__",
|
|
20
|
+
authEndpoint: "/realms/{realm}/protocol/openid-connect/token",
|
|
21
|
+
authRequestFormat: "form",
|
|
22
|
+
authGrantType: "password",
|
|
23
|
+
authScope: "openid profile email",
|
|
24
|
+
clientId: "app-id",
|
|
25
|
+
clientSecret: "secret"
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Variáveis de ambiente (exemplo local)
|
|
30
|
+
|
|
31
|
+
No app de exemplo (Vite), os valores sensíveis são lidos de um arquivo local de ambiente. Crie um arquivo `.env.local` na pasta do app e preencha as variáveis abaixo (o arquivo fica ignorado por padrão pelo `.gitignore` via `*.local`).
|
|
32
|
+
|
|
33
|
+
```dotenv
|
|
34
|
+
VITE_NEOG_BASE_URL=
|
|
35
|
+
VITE_NEOG_AUTH_BASE_URL=
|
|
36
|
+
VITE_NEOG_AUTH_REALM=
|
|
37
|
+
VITE_NEOG_AUTH_ENDPOINT=/realms/{realm}/protocol/openid-connect/token
|
|
38
|
+
VITE_NEOG_AUTH_REQUEST_FORMAT=form
|
|
39
|
+
VITE_NEOG_AUTH_GRANT_TYPE=password
|
|
40
|
+
VITE_NEOG_AUTH_SCOPE=openid profile email
|
|
41
|
+
VITE_NEOG_CLIENT_ID=
|
|
42
|
+
VITE_NEOG_CLIENT_SECRET=
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
No exemplo, o `createNeogAuth` usa essas variáveis, evitando valores fixos no repositório.
|
|
46
|
+
|
|
47
|
+
## AuthProvider e useAuth
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
function App() {
|
|
51
|
+
return (
|
|
52
|
+
<AuthProvider>
|
|
53
|
+
<Routes />
|
|
54
|
+
</AuthProvider>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function LoginButton() {
|
|
59
|
+
const { login, logout, isAuthenticated, loading } = useAuth();
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
<button disabled={loading} onClick={() => login("user", "pass")}>Login</button>
|
|
63
|
+
<button onClick={logout}>Logout</button>
|
|
64
|
+
<span>{isAuthenticated ? "ok" : "off"}</span>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## NeogClient.post
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
const client = createNeogClient();
|
|
74
|
+
|
|
75
|
+
const response = await client.get<{ id: string }>("/status");
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Guia de migração (resumido)
|
|
80
|
+
|
|
81
|
+
1. Instale o pacote:
|
|
82
|
+
```bash
|
|
83
|
+
npm install @neog-cloud/neog-api-client
|
|
84
|
+
```
|
|
85
|
+
2. Crie a instância:
|
|
86
|
+
```ts
|
|
87
|
+
import { createNeogAuth } from "@neog-cloud/neog-api-client";
|
|
88
|
+
|
|
89
|
+
const { AuthProvider, useAuth, createNeogClient } = createNeogAuth({
|
|
90
|
+
baseUrl: "https://api_neog",
|
|
91
|
+
authBaseUrl: "https://iam_neog",
|
|
92
|
+
authRealm: "__REALM__",
|
|
93
|
+
authEndpoint: "/realms/{realm}/protocol/openid-connect/token",
|
|
94
|
+
authRequestFormat: "form",
|
|
95
|
+
authGrantType: "password",
|
|
96
|
+
authScope: "openid profile email",
|
|
97
|
+
clientId: "app-id",
|
|
98
|
+
clientSecret: "secret",
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
3. Substitua o AuthProvider local:
|
|
102
|
+
```tsx
|
|
103
|
+
function App() {
|
|
104
|
+
return (
|
|
105
|
+
<AuthProvider>
|
|
106
|
+
<Routes />
|
|
107
|
+
</AuthProvider>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
4. Substitua os imports de `useAuth` locais pelos do pacote (mesmos campos).
|
|
112
|
+
5. Substitua as chamadas HTTP por `createNeogClient().post(...)`.
|
|
113
|
+
|
|
114
|
+
## Persistência e refresh
|
|
115
|
+
|
|
116
|
+
- Tokens são persistidos em `localStorage` na chave configurável (default: `neog_auth`).
|
|
117
|
+
- Em caso de `401`, o cliente tenta refresh com `tokenRefreshEndpoint`.
|
|
118
|
+
- Se a API não fornecer refresh token, um `401` exige novo login.
|
|
119
|
+
|
|
120
|
+
## Segurança
|
|
121
|
+
|
|
122
|
+
O uso de `clientSecret` no frontend expõe o segredo no bundle. Esta configuração deve ser usada apenas em ambientes controlados e/ou temporariamente, até a adoção de um fluxo mais seguro (ex: BFF ou PKCE).
|
|
123
|
+
|
|
124
|
+
## Desenvolvimento
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm run build
|
|
128
|
+
npm test
|
|
129
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AuthContextType, AuthState } from "./types";
|
|
3
|
+
import { NeogAuthOptions } from "./options";
|
|
4
|
+
export type AuthProviderFactory = {
|
|
5
|
+
AuthProvider: React.FC<{
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}>;
|
|
8
|
+
useAuth: () => AuthContextType;
|
|
9
|
+
getToken: () => string | null;
|
|
10
|
+
setToken: (token: string | null, refreshToken?: string | null, user?: AuthState["user"]) => void;
|
|
11
|
+
logout: () => void;
|
|
12
|
+
refreshAccessToken: () => Promise<string | null>;
|
|
13
|
+
};
|
|
14
|
+
export declare const createAuthProvider: (options: NeogAuthOptions) => AuthProviderFactory;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type NeogAuthOptions = {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
authBaseUrl?: string;
|
|
4
|
+
authRealm?: string;
|
|
5
|
+
authEndpoint: string;
|
|
6
|
+
authRequestFormat?: "json" | "form";
|
|
7
|
+
authGrantType?: string;
|
|
8
|
+
authScope?: string;
|
|
9
|
+
clientId: string;
|
|
10
|
+
clientSecret?: string;
|
|
11
|
+
storageKey?: string;
|
|
12
|
+
tokenRefreshEndpoint?: string;
|
|
13
|
+
requestTimeoutMs?: number;
|
|
14
|
+
onRequestLog?: (info: {
|
|
15
|
+
url: string;
|
|
16
|
+
method: string;
|
|
17
|
+
}) => void;
|
|
18
|
+
onResponseLog?: (info: {
|
|
19
|
+
url: string;
|
|
20
|
+
status: number;
|
|
21
|
+
}) => void;
|
|
22
|
+
onErrorLog?: (info: {
|
|
23
|
+
url: string;
|
|
24
|
+
status?: number;
|
|
25
|
+
message: string;
|
|
26
|
+
}) => void;
|
|
27
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface StoredAuthState {
|
|
2
|
+
accessToken: string | null;
|
|
3
|
+
refreshToken?: string | null;
|
|
4
|
+
expiresAt?: number | null;
|
|
5
|
+
user?: {
|
|
6
|
+
id: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
} | null;
|
|
10
|
+
}
|
|
11
|
+
export declare const saveAuthState: (storageKey: string, state: StoredAuthState) => void;
|
|
12
|
+
export declare const loadAuthState: (storageKey: string) => StoredAuthState | null;
|
|
13
|
+
export declare const clearAuthState: (storageKey: string) => void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface AuthContextType {
|
|
2
|
+
token: string | null;
|
|
3
|
+
refreshToken?: string | null;
|
|
4
|
+
user?: {
|
|
5
|
+
id: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
} | null;
|
|
9
|
+
isAuthenticated: boolean;
|
|
10
|
+
loading: boolean;
|
|
11
|
+
error?: string | null;
|
|
12
|
+
login: (username: string, password: string) => Promise<void>;
|
|
13
|
+
logout: () => void;
|
|
14
|
+
getToken: () => string | null;
|
|
15
|
+
setToken?: (token: string, refreshToken?: string) => void;
|
|
16
|
+
}
|
|
17
|
+
export type AuthState = {
|
|
18
|
+
token: string | null;
|
|
19
|
+
refreshToken?: string | null;
|
|
20
|
+
user?: {
|
|
21
|
+
id: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
email?: string;
|
|
24
|
+
} | null;
|
|
25
|
+
isAuthenticated: boolean;
|
|
26
|
+
};
|
|
27
|
+
export type TokenResponse = {
|
|
28
|
+
access_token: string;
|
|
29
|
+
refresh_token?: string;
|
|
30
|
+
expires_in?: number;
|
|
31
|
+
expires_at?: number;
|
|
32
|
+
user?: {
|
|
33
|
+
id: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
email?: string;
|
|
36
|
+
} | null;
|
|
37
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios";
|
|
2
|
+
import { ClientOptions, NeogClient } from "./types";
|
|
3
|
+
export type RefreshTokenHandler = () => Promise<string | null>;
|
|
4
|
+
export type GetTokenHandler = () => string | null;
|
|
5
|
+
export type LogoutHandler = () => void;
|
|
6
|
+
export type CreateClientDeps = {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
getToken: GetTokenHandler;
|
|
9
|
+
refreshToken: RefreshTokenHandler;
|
|
10
|
+
logout: LogoutHandler;
|
|
11
|
+
requestTimeoutMs?: number;
|
|
12
|
+
defaultHeaders?: Record<string, string>;
|
|
13
|
+
onRequestLog?: (info: {
|
|
14
|
+
url: string;
|
|
15
|
+
method: string;
|
|
16
|
+
}) => void;
|
|
17
|
+
onResponseLog?: (info: {
|
|
18
|
+
url: string;
|
|
19
|
+
status: number;
|
|
20
|
+
}) => void;
|
|
21
|
+
onErrorLog?: (info: {
|
|
22
|
+
url: string;
|
|
23
|
+
status?: number;
|
|
24
|
+
message: string;
|
|
25
|
+
}) => void;
|
|
26
|
+
};
|
|
27
|
+
export declare const createNeogClient: (deps: CreateClientDeps, opts?: ClientOptions) => NeogClient & {
|
|
28
|
+
__axios?: AxiosInstance;
|
|
29
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface Response<T> {
|
|
2
|
+
status: "success" | "error" | "valid" | "unchecked" | "warning";
|
|
3
|
+
message?: string;
|
|
4
|
+
tecnicalMessage?: string;
|
|
5
|
+
count: number;
|
|
6
|
+
page: number;
|
|
7
|
+
version: string;
|
|
8
|
+
objects: T[];
|
|
9
|
+
}
|
|
10
|
+
export type Operator = ">" | "<" | "=" | ">=" | "<=" | "like" | "is null" | "is not null" | "" | "in" | "eq" | "ne" | "gt" | "ge" | "lt" | "le" | "notLike" | "notIn" | "isNull" | "isNotNull" | "between" | "notBetween";
|
|
11
|
+
export interface FilterField {
|
|
12
|
+
column: string;
|
|
13
|
+
type?: string;
|
|
14
|
+
value?: any;
|
|
15
|
+
operator: Operator;
|
|
16
|
+
caption?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface OrderField {
|
|
19
|
+
column: string;
|
|
20
|
+
direction: "asc" | "desc";
|
|
21
|
+
}
|
|
22
|
+
export interface Request<T> {
|
|
23
|
+
compRefid?: string;
|
|
24
|
+
branchRefid?: string;
|
|
25
|
+
version: string;
|
|
26
|
+
message?: string;
|
|
27
|
+
objects?: T[];
|
|
28
|
+
filters?: FilterField[];
|
|
29
|
+
orderBy?: OrderField[];
|
|
30
|
+
params?: FilterField[];
|
|
31
|
+
}
|
|
32
|
+
export type ClientOptions = {
|
|
33
|
+
timeoutMs?: number;
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
};
|
|
36
|
+
export interface NeogClient {
|
|
37
|
+
post<TRequest, TResponse>(methodPath: string, body: Request<TRequest>): Promise<Response<TResponse>>;
|
|
38
|
+
setAuthHeader(token: string | null): void;
|
|
39
|
+
get<TResponse>(path: string, params?: any): Promise<TResponse>;
|
|
40
|
+
}
|