hightjs 0.2.42 → 0.2.45
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/.idea/copilotDiffState.xml +67 -0
- package/README.md +26 -514
- package/dist/auth/core.js +3 -3
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +2 -1
- package/dist/auth/providers/google.d.ts +63 -0
- package/dist/auth/providers/google.js +186 -0
- package/dist/auth/providers.d.ts +1 -0
- package/dist/auth/providers.js +3 -1
- package/dist/auth/types.d.ts +6 -7
- package/dist/bin/hightjs.js +393 -0
- package/dist/client/entry.client.js +11 -1
- package/dist/hotReload.d.ts +8 -1
- package/dist/hotReload.js +304 -144
- package/dist/index.d.ts +2 -1
- package/dist/index.js +20 -33
- package/dist/renderer.js +1 -1
- package/dist/router.d.ts +24 -1
- package/dist/router.js +201 -2
- package/dist/types.d.ts +19 -1
- package/docs/README.md +59 -0
- package/docs/adapters.md +7 -0
- package/docs/arquivos-especiais.md +10 -0
- package/docs/autenticacao.md +212 -0
- package/docs/checklist.md +9 -0
- package/docs/cli.md +21 -0
- package/docs/estrutura.md +20 -0
- package/docs/faq.md +10 -0
- package/docs/hot-reload.md +5 -0
- package/docs/middlewares.md +73 -0
- package/docs/rotas-backend.md +45 -0
- package/docs/rotas-frontend.md +66 -0
- package/docs/seguranca.md +8 -0
- package/docs/websocket.md +45 -0
- package/package.json +1 -1
- package/src/auth/core.ts +3 -3
- package/src/auth/index.ts +2 -3
- package/src/auth/providers/google.ts +218 -0
- package/src/auth/providers.ts +1 -1
- package/src/auth/types.ts +3 -8
- package/src/bin/hightjs.js +475 -0
- package/src/client/entry.client.tsx +12 -1
- package/src/hotReload.ts +333 -147
- package/src/index.ts +58 -51
- package/src/renderer.tsx +1 -1
- package/src/router.ts +230 -3
- package/src/types.ts +24 -1
- package/dist/adapters/starters/express.d.ts +0 -0
- package/dist/adapters/starters/express.js +0 -1
- package/dist/adapters/starters/factory.d.ts +0 -0
- package/dist/adapters/starters/factory.js +0 -1
- package/dist/adapters/starters/fastify.d.ts +0 -0
- package/dist/adapters/starters/fastify.js +0 -1
- package/dist/adapters/starters/index.d.ts +0 -0
- package/dist/adapters/starters/index.js +0 -1
- package/dist/adapters/starters/native.d.ts +0 -0
- package/dist/adapters/starters/native.js +0 -1
- package/dist/auth/example.d.ts +0 -40
- package/dist/auth/example.js +0 -104
- package/dist/client/ErrorBoundary.d.ts +0 -16
- package/dist/client/ErrorBoundary.js +0 -181
- package/dist/client/routerContext.d.ts +0 -26
- package/dist/client/routerContext.js +0 -62
- package/dist/eslint/index.d.ts +0 -32
- package/dist/eslint/index.js +0 -15
- package/dist/eslint/use-client-rule.d.ts +0 -19
- package/dist/eslint/use-client-rule.js +0 -99
- package/dist/eslintSetup.d.ts +0 -0
- package/dist/eslintSetup.js +0 -1
- package/dist/example/src/web/routes/index.d.ts +0 -3
- package/dist/example/src/web/routes/index.js +0 -15
- package/dist/typescript/use-client-plugin.d.ts +0 -5
- package/dist/typescript/use-client-plugin.js +0 -113
- package/dist/validation.d.ts +0 -0
- package/dist/validation.js +0 -1
- package/src/auth/example.ts +0 -115
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
2
|
-
interface Props {
|
|
3
|
-
children: ReactNode;
|
|
4
|
-
}
|
|
5
|
-
interface State {
|
|
6
|
-
hasError: boolean;
|
|
7
|
-
error?: Error;
|
|
8
|
-
errorInfo?: ErrorInfo;
|
|
9
|
-
}
|
|
10
|
-
export declare class ErrorBoundary extends Component<Props, State> {
|
|
11
|
-
constructor(props: Props);
|
|
12
|
-
static getDerivedStateFromError(error: Error): State;
|
|
13
|
-
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
14
|
-
render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
15
|
-
}
|
|
16
|
-
export {};
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ErrorBoundary = void 0;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
6
|
-
class ErrorBoundary extends react_1.Component {
|
|
7
|
-
constructor(props) {
|
|
8
|
-
super(props);
|
|
9
|
-
this.state = { hasError: false };
|
|
10
|
-
}
|
|
11
|
-
static getDerivedStateFromError(error) {
|
|
12
|
-
// Atualiza o state para que a próxima renderização mostre a UI de erro
|
|
13
|
-
return { hasError: true, error };
|
|
14
|
-
}
|
|
15
|
-
componentDidCatch(error, errorInfo) {
|
|
16
|
-
console.error('ErrorBoundary capturou um erro:', error, errorInfo);
|
|
17
|
-
this.setState({
|
|
18
|
-
error,
|
|
19
|
-
errorInfo
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
render() {
|
|
23
|
-
if (this.state.hasError) {
|
|
24
|
-
return (0, jsx_runtime_1.jsx)(ErrorDisplay, { error: this.state.error, errorInfo: this.state.errorInfo });
|
|
25
|
-
}
|
|
26
|
-
return this.props.children;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.ErrorBoundary = ErrorBoundary;
|
|
30
|
-
function ErrorDisplay({ error, errorInfo }) {
|
|
31
|
-
const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
32
|
-
return ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
33
|
-
fontFamily: 'system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
34
|
-
height: '100vh',
|
|
35
|
-
padding: '20px',
|
|
36
|
-
backgroundColor: isDark ? '#0a0a0a' : '#ffffff',
|
|
37
|
-
color: isDark ? '#fafafa' : '#171717',
|
|
38
|
-
overflow: 'auto'
|
|
39
|
-
}, children: (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
40
|
-
maxWidth: '800px',
|
|
41
|
-
margin: '0 auto',
|
|
42
|
-
paddingTop: '40px'
|
|
43
|
-
}, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
|
|
44
|
-
borderBottom: `1px solid ${isDark ? '#262626' : '#e5e5e5'}`,
|
|
45
|
-
paddingBottom: '20px',
|
|
46
|
-
marginBottom: '30px'
|
|
47
|
-
}, children: [(0, jsx_runtime_1.jsx)("h1", { style: {
|
|
48
|
-
fontSize: '24px',
|
|
49
|
-
fontWeight: '600',
|
|
50
|
-
margin: '0 0 10px 0',
|
|
51
|
-
color: '#dc2626'
|
|
52
|
-
}, children: "\u274C Erro na Aplica\u00E7\u00E3o" }), (0, jsx_runtime_1.jsx)("p", { style: {
|
|
53
|
-
fontSize: '16px',
|
|
54
|
-
margin: '0',
|
|
55
|
-
color: isDark ? '#a3a3a3' : '#737373'
|
|
56
|
-
}, children: "Ocorreu um erro inesperado na aplica\u00E7\u00E3o. Veja os detalhes abaixo:" })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
57
|
-
backgroundColor: isDark ? '#1c1917' : '#fef2f2',
|
|
58
|
-
border: `1px solid ${isDark ? '#451a03' : '#fecaca'}`,
|
|
59
|
-
borderRadius: '8px',
|
|
60
|
-
padding: '20px',
|
|
61
|
-
marginBottom: '20px'
|
|
62
|
-
}, children: [(0, jsx_runtime_1.jsx)("h2", { style: {
|
|
63
|
-
fontSize: '18px',
|
|
64
|
-
fontWeight: '600',
|
|
65
|
-
margin: '0 0 10px 0',
|
|
66
|
-
color: '#dc2626'
|
|
67
|
-
}, children: "Mensagem do Erro:" }), (0, jsx_runtime_1.jsx)("p", { style: {
|
|
68
|
-
fontSize: '14px',
|
|
69
|
-
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
70
|
-
backgroundColor: isDark ? '#0c0a09' : '#ffffff',
|
|
71
|
-
padding: '15px',
|
|
72
|
-
borderRadius: '6px',
|
|
73
|
-
border: `1px solid ${isDark ? '#292524' : '#e5e5e5'}`,
|
|
74
|
-
margin: '0',
|
|
75
|
-
whiteSpace: 'pre-wrap',
|
|
76
|
-
overflow: 'auto'
|
|
77
|
-
}, children: error?.message || 'Erro desconhecido' })] }), error?.stack && ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
78
|
-
backgroundColor: isDark ? '#0c0a09' : '#fafafa',
|
|
79
|
-
border: `1px solid ${isDark ? '#292524' : '#e5e5e5'}`,
|
|
80
|
-
borderRadius: '8px',
|
|
81
|
-
padding: '20px',
|
|
82
|
-
marginBottom: '20px'
|
|
83
|
-
}, children: [(0, jsx_runtime_1.jsx)("h2", { style: {
|
|
84
|
-
fontSize: '18px',
|
|
85
|
-
fontWeight: '600',
|
|
86
|
-
margin: '0 0 10px 0',
|
|
87
|
-
color: isDark ? '#fafafa' : '#171717'
|
|
88
|
-
}, children: "Stack Trace:" }), (0, jsx_runtime_1.jsx)("pre", { style: {
|
|
89
|
-
fontSize: '12px',
|
|
90
|
-
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
91
|
-
backgroundColor: isDark ? '#1c1917' : '#ffffff',
|
|
92
|
-
padding: '15px',
|
|
93
|
-
borderRadius: '6px',
|
|
94
|
-
border: `1px solid ${isDark ? '#44403c' : '#d4d4d4'}`,
|
|
95
|
-
margin: '0',
|
|
96
|
-
overflow: 'auto',
|
|
97
|
-
whiteSpace: 'pre-wrap',
|
|
98
|
-
color: isDark ? '#e5e5e5' : '#525252'
|
|
99
|
-
}, children: error.stack })] })), errorInfo?.componentStack && ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
100
|
-
backgroundColor: isDark ? '#0c0a09' : '#fafafa',
|
|
101
|
-
border: `1px solid ${isDark ? '#292524' : '#e5e5e5'}`,
|
|
102
|
-
borderRadius: '8px',
|
|
103
|
-
padding: '20px',
|
|
104
|
-
marginBottom: '20px'
|
|
105
|
-
}, children: [(0, jsx_runtime_1.jsx)("h2", { style: {
|
|
106
|
-
fontSize: '18px',
|
|
107
|
-
fontWeight: '600',
|
|
108
|
-
margin: '0 0 10px 0',
|
|
109
|
-
color: isDark ? '#fafafa' : '#171717'
|
|
110
|
-
}, children: "Component Stack:" }), (0, jsx_runtime_1.jsx)("pre", { style: {
|
|
111
|
-
fontSize: '12px',
|
|
112
|
-
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
113
|
-
backgroundColor: isDark ? '#1c1917' : '#ffffff',
|
|
114
|
-
padding: '15px',
|
|
115
|
-
borderRadius: '6px',
|
|
116
|
-
border: `1px solid ${isDark ? '#44403c' : '#d4d4d4'}`,
|
|
117
|
-
margin: '0',
|
|
118
|
-
overflow: 'auto',
|
|
119
|
-
whiteSpace: 'pre-wrap',
|
|
120
|
-
color: isDark ? '#e5e5e5' : '#525252'
|
|
121
|
-
}, children: errorInfo.componentStack })] })), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
122
|
-
display: 'flex',
|
|
123
|
-
gap: '10px',
|
|
124
|
-
marginTop: '30px'
|
|
125
|
-
}, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => window.location.reload(), style: {
|
|
126
|
-
backgroundColor: '#2563eb',
|
|
127
|
-
color: '#ffffff',
|
|
128
|
-
border: 'none',
|
|
129
|
-
padding: '12px 20px',
|
|
130
|
-
borderRadius: '6px',
|
|
131
|
-
fontSize: '14px',
|
|
132
|
-
fontWeight: '500',
|
|
133
|
-
cursor: 'pointer',
|
|
134
|
-
transition: 'background-color 0.2s'
|
|
135
|
-
}, onMouseEnter: (e) => {
|
|
136
|
-
e.currentTarget.style.backgroundColor = '#1d4ed8';
|
|
137
|
-
}, onMouseLeave: (e) => {
|
|
138
|
-
e.currentTarget.style.backgroundColor = '#2563eb';
|
|
139
|
-
}, children: "\uD83D\uDD04 Recarregar P\u00E1gina" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => {
|
|
140
|
-
navigator.clipboard?.writeText(`
|
|
141
|
-
Erro: ${error?.message || 'Erro desconhecido'}
|
|
142
|
-
|
|
143
|
-
Stack Trace:
|
|
144
|
-
${error?.stack || 'N/A'}
|
|
145
|
-
|
|
146
|
-
Component Stack:
|
|
147
|
-
${errorInfo?.componentStack || 'N/A'}
|
|
148
|
-
`.trim());
|
|
149
|
-
alert('Detalhes do erro copiados para a área de transferência!');
|
|
150
|
-
}, style: {
|
|
151
|
-
backgroundColor: isDark ? '#374151' : '#f3f4f6',
|
|
152
|
-
color: isDark ? '#fafafa' : '#171717',
|
|
153
|
-
border: `1px solid ${isDark ? '#4b5563' : '#d1d5db'}`,
|
|
154
|
-
padding: '12px 20px',
|
|
155
|
-
borderRadius: '6px',
|
|
156
|
-
fontSize: '14px',
|
|
157
|
-
fontWeight: '500',
|
|
158
|
-
cursor: 'pointer',
|
|
159
|
-
transition: 'background-color 0.2s'
|
|
160
|
-
}, onMouseEnter: (e) => {
|
|
161
|
-
e.currentTarget.style.backgroundColor = isDark ? '#4b5563' : '#e5e7eb';
|
|
162
|
-
}, onMouseLeave: (e) => {
|
|
163
|
-
e.currentTarget.style.backgroundColor = isDark ? '#374151' : '#f3f4f6';
|
|
164
|
-
}, children: "\uD83D\uDCCB Copiar Detalhes" })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
165
|
-
marginTop: '40px',
|
|
166
|
-
padding: '20px',
|
|
167
|
-
backgroundColor: isDark ? '#1e1b1a' : '#f8fafc',
|
|
168
|
-
border: `1px solid ${isDark ? '#3c2e2a' : '#e2e8f0'}`,
|
|
169
|
-
borderRadius: '8px'
|
|
170
|
-
}, children: [(0, jsx_runtime_1.jsx)("h3", { style: {
|
|
171
|
-
fontSize: '16px',
|
|
172
|
-
fontWeight: '600',
|
|
173
|
-
margin: '0 0 10px 0',
|
|
174
|
-
color: isDark ? '#fbbf24' : '#d97706'
|
|
175
|
-
}, children: "\uD83D\uDCA1 Para Desenvolvedores:" }), (0, jsx_runtime_1.jsxs)("ul", { style: {
|
|
176
|
-
fontSize: '14px',
|
|
177
|
-
margin: '0',
|
|
178
|
-
paddingLeft: '20px',
|
|
179
|
-
color: isDark ? '#d1d5db' : '#4b5563'
|
|
180
|
-
}, children: [(0, jsx_runtime_1.jsx)("li", { children: "Verifique o console do navegador para mais detalhes" }), (0, jsx_runtime_1.jsx)("li", { children: "Verifique se todos os arquivos foram buildados corretamente" }), (0, jsx_runtime_1.jsx)("li", { children: "Se for erro 404 em main.js, verifique se o servidor est\u00E1 rodando" }), (0, jsx_runtime_1.jsx)("li", { children: "Use as ferramentas de desenvolvimento do navegador para debugar" })] })] })] }) }));
|
|
181
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
interface RouterContextType {
|
|
3
|
-
pathname: string;
|
|
4
|
-
query: URLSearchParams;
|
|
5
|
-
push: (url: string) => Promise<void>;
|
|
6
|
-
replace: (url: string) => Promise<void>;
|
|
7
|
-
back: () => void;
|
|
8
|
-
forward: () => void;
|
|
9
|
-
refresh: () => void;
|
|
10
|
-
}
|
|
11
|
-
export declare function RouterProvider({ children }: {
|
|
12
|
-
children: React.ReactNode;
|
|
13
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
14
|
-
/**
|
|
15
|
-
* Hook para acessar o router dentro de componentes React
|
|
16
|
-
*/
|
|
17
|
-
export declare function useRouter(): RouterContextType;
|
|
18
|
-
/**
|
|
19
|
-
* Hook para acessar apenas o pathname atual
|
|
20
|
-
*/
|
|
21
|
-
export declare function usePathname(): string;
|
|
22
|
-
/**
|
|
23
|
-
* Hook para acessar apenas os query parameters
|
|
24
|
-
*/
|
|
25
|
-
export declare function useSearchParams(): URLSearchParams;
|
|
26
|
-
export {};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RouterProvider = RouterProvider;
|
|
4
|
-
exports.useRouter = useRouter;
|
|
5
|
-
exports.usePathname = usePathname;
|
|
6
|
-
exports.useSearchParams = useSearchParams;
|
|
7
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
-
const react_1 = require("react");
|
|
9
|
-
const clientRouter_1 = require("./clientRouter");
|
|
10
|
-
const RouterContext = (0, react_1.createContext)(null);
|
|
11
|
-
function RouterProvider({ children }) {
|
|
12
|
-
const [pathname, setPathname] = (0, react_1.useState)(clientRouter_1.router.pathname);
|
|
13
|
-
const [query, setQuery] = (0, react_1.useState)(clientRouter_1.router.query);
|
|
14
|
-
(0, react_1.useEffect)(() => {
|
|
15
|
-
const updateRoute = () => {
|
|
16
|
-
setPathname(clientRouter_1.router.pathname);
|
|
17
|
-
setQuery(clientRouter_1.router.query);
|
|
18
|
-
};
|
|
19
|
-
// Subscribe to router changes
|
|
20
|
-
const unsubscribe = clientRouter_1.router.subscribe(updateRoute);
|
|
21
|
-
// Also listen to browser back/forward
|
|
22
|
-
window.addEventListener('popstate', updateRoute);
|
|
23
|
-
return () => {
|
|
24
|
-
unsubscribe();
|
|
25
|
-
window.removeEventListener('popstate', updateRoute);
|
|
26
|
-
};
|
|
27
|
-
}, []);
|
|
28
|
-
const value = {
|
|
29
|
-
pathname,
|
|
30
|
-
query,
|
|
31
|
-
push: clientRouter_1.router.push.bind(clientRouter_1.router),
|
|
32
|
-
replace: clientRouter_1.router.replace.bind(clientRouter_1.router),
|
|
33
|
-
back: clientRouter_1.router.back.bind(clientRouter_1.router),
|
|
34
|
-
forward: clientRouter_1.router.forward.bind(clientRouter_1.router),
|
|
35
|
-
refresh: clientRouter_1.router.refresh.bind(clientRouter_1.router),
|
|
36
|
-
};
|
|
37
|
-
return ((0, jsx_runtime_1.jsx)(RouterContext.Provider, { value: value, children: children }));
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Hook para acessar o router dentro de componentes React
|
|
41
|
-
*/
|
|
42
|
-
function useRouter() {
|
|
43
|
-
const context = (0, react_1.useContext)(RouterContext);
|
|
44
|
-
if (!context) {
|
|
45
|
-
throw new Error('useRouter deve ser usado dentro de um RouterProvider');
|
|
46
|
-
}
|
|
47
|
-
return context;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Hook para acessar apenas o pathname atual
|
|
51
|
-
*/
|
|
52
|
-
function usePathname() {
|
|
53
|
-
const { pathname } = useRouter();
|
|
54
|
-
return pathname;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Hook para acessar apenas os query parameters
|
|
58
|
-
*/
|
|
59
|
-
function useSearchParams() {
|
|
60
|
-
const { query } = useRouter();
|
|
61
|
-
return query;
|
|
62
|
-
}
|
package/dist/eslint/index.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export let rules: {
|
|
2
|
-
'require-use-client': {
|
|
3
|
-
meta: {
|
|
4
|
-
type: string;
|
|
5
|
-
docs: {
|
|
6
|
-
description: string;
|
|
7
|
-
category: string;
|
|
8
|
-
recommended: boolean;
|
|
9
|
-
};
|
|
10
|
-
fixable: string;
|
|
11
|
-
schema: never[];
|
|
12
|
-
messages: {
|
|
13
|
-
missingUseClient: string;
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
create(context: any): {
|
|
17
|
-
Program(node: any): void;
|
|
18
|
-
ImportDeclaration(node: any): void;
|
|
19
|
-
CallExpression(node: any): void;
|
|
20
|
-
'Program:exit'(): void;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
export namespace configs {
|
|
25
|
-
namespace recommended {
|
|
26
|
-
export let plugins: string[];
|
|
27
|
-
let rules_1: {
|
|
28
|
-
'hightjs/require-use-client': string;
|
|
29
|
-
};
|
|
30
|
-
export { rules_1 as rules };
|
|
31
|
-
}
|
|
32
|
-
}
|
package/dist/eslint/index.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const useClientRule = require('./use-client-rule');
|
|
3
|
-
module.exports = {
|
|
4
|
-
rules: {
|
|
5
|
-
'require-use-client': useClientRule,
|
|
6
|
-
},
|
|
7
|
-
configs: {
|
|
8
|
-
recommended: {
|
|
9
|
-
plugins: ['hightjs'],
|
|
10
|
-
rules: {
|
|
11
|
-
'hightjs/require-use-client': 'error',
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export namespace meta {
|
|
2
|
-
let type: string;
|
|
3
|
-
namespace docs {
|
|
4
|
-
let description: string;
|
|
5
|
-
let category: string;
|
|
6
|
-
let recommended: boolean;
|
|
7
|
-
}
|
|
8
|
-
let fixable: string;
|
|
9
|
-
let schema: never[];
|
|
10
|
-
namespace messages {
|
|
11
|
-
let missingUseClient: string;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export function create(context: any): {
|
|
15
|
-
Program(node: any): void;
|
|
16
|
-
ImportDeclaration(node: any): void;
|
|
17
|
-
CallExpression(node: any): void;
|
|
18
|
-
'Program:exit'(): void;
|
|
19
|
-
};
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* ESLint rule: require-use-client
|
|
4
|
-
* Força o uso de "use client" quando React ou hooks são importados
|
|
5
|
-
*/
|
|
6
|
-
module.exports = {
|
|
7
|
-
meta: {
|
|
8
|
-
type: 'problem',
|
|
9
|
-
docs: {
|
|
10
|
-
description: 'Require "use client" directive when importing React or React hooks',
|
|
11
|
-
category: 'Best Practices',
|
|
12
|
-
recommended: true,
|
|
13
|
-
},
|
|
14
|
-
fixable: 'code',
|
|
15
|
-
schema: [],
|
|
16
|
-
messages: {
|
|
17
|
-
missingUseClient: 'Arquivos que importam React ou hooks devem começar com "use client"',
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
create(context) {
|
|
21
|
-
let hasReactImport = false;
|
|
22
|
-
let hasReactHooks = false;
|
|
23
|
-
let hasUseClient = false;
|
|
24
|
-
let firstNode = null;
|
|
25
|
-
// Lista de hooks do React que requerem "use client"
|
|
26
|
-
const reactHooks = [
|
|
27
|
-
'useState', 'useEffect', 'useContext', 'useReducer',
|
|
28
|
-
'useCallback', 'useMemo', 'useRef', 'useImperativeHandle',
|
|
29
|
-
'useLayoutEffect', 'useDebugValue', 'useDeferredValue',
|
|
30
|
-
'useTransition', 'useId', 'useSyncExternalStore',
|
|
31
|
-
'useInsertionEffect'
|
|
32
|
-
];
|
|
33
|
-
return {
|
|
34
|
-
Program(node) {
|
|
35
|
-
firstNode = node;
|
|
36
|
-
// Verifica se já tem "use client" no início do arquivo
|
|
37
|
-
const sourceCode = context.getSourceCode();
|
|
38
|
-
const firstToken = sourceCode.getFirstToken(node);
|
|
39
|
-
if (firstToken && firstToken.type === 'String') {
|
|
40
|
-
const value = firstToken.value;
|
|
41
|
-
if (value === '"use client"' || value === "'use client'") {
|
|
42
|
-
hasUseClient = true;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
// Também verifica comentários
|
|
46
|
-
const comments = sourceCode.getAllComments();
|
|
47
|
-
if (comments.length > 0) {
|
|
48
|
-
const firstComment = comments[0];
|
|
49
|
-
if (firstComment.value.trim() === 'use client') {
|
|
50
|
-
hasUseClient = true;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
ImportDeclaration(node) {
|
|
55
|
-
const source = node.source.value;
|
|
56
|
-
// Verifica se importa do React
|
|
57
|
-
if (source === 'react' || source === 'react/jsx-runtime') {
|
|
58
|
-
hasReactImport = true;
|
|
59
|
-
// Verifica se importa hooks específicos
|
|
60
|
-
if (node.specifiers) {
|
|
61
|
-
for (const specifier of node.specifiers) {
|
|
62
|
-
if (specifier.type === 'ImportSpecifier' &&
|
|
63
|
-
reactHooks.includes(specifier.imported.name)) {
|
|
64
|
-
hasReactHooks = true;
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
CallExpression(node) {
|
|
72
|
-
// Verifica se usa hooks do React diretamente
|
|
73
|
-
if (node.callee.type === 'Identifier' &&
|
|
74
|
-
reactHooks.includes(node.callee.name)) {
|
|
75
|
-
hasReactHooks = true;
|
|
76
|
-
}
|
|
77
|
-
// Verifica se usa React.useState, React.useEffect, etc.
|
|
78
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
79
|
-
node.callee.object.name === 'React' &&
|
|
80
|
-
reactHooks.includes(node.callee.property.name)) {
|
|
81
|
-
hasReactHooks = true;
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
'Program:exit'() {
|
|
85
|
-
// Se importa React ou usa hooks mas não tem "use client"
|
|
86
|
-
if ((hasReactImport || hasReactHooks) && !hasUseClient) {
|
|
87
|
-
context.report({
|
|
88
|
-
node: firstNode,
|
|
89
|
-
messageId: 'missingUseClient',
|
|
90
|
-
fix(fixer) {
|
|
91
|
-
// Auto-fix: adiciona "use client" no início do arquivo
|
|
92
|
-
return fixer.insertTextBefore(firstNode, '"use client";\n\n');
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
},
|
|
99
|
-
};
|
package/dist/eslintSetup.d.ts
DELETED
|
File without changes
|
package/dist/eslintSetup.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.config = void 0;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
function Home() {
|
|
6
|
-
return ((0, jsx_runtime_1.jsx)("h1", { children: "OL\u00C1 MUNDINHO MEU AMIGUINHO, VAMOS TRANSA?" }));
|
|
7
|
-
}
|
|
8
|
-
exports.config = {
|
|
9
|
-
pattern: '/',
|
|
10
|
-
component: Home,
|
|
11
|
-
generateMetadata: () => ({
|
|
12
|
-
title: 'HightJS | Home'
|
|
13
|
-
})
|
|
14
|
-
};
|
|
15
|
-
exports.default = exports.config;
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* TypeScript Plugin: require-use-client
|
|
4
|
-
* Integra a validação "use client" diretamente no TypeScript
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.default = createPlugin;
|
|
8
|
-
const defaultConfig = {
|
|
9
|
-
enabled: true,
|
|
10
|
-
severity: 'error'
|
|
11
|
-
};
|
|
12
|
-
function isReactImport(node) {
|
|
13
|
-
if (!node.moduleSpecifier || node.moduleSpecifier.kind !== 10) { // StringLiteral = 10
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
const moduleName = node.moduleSpecifier.text;
|
|
17
|
-
return moduleName === 'react' || moduleName === 'react/jsx-runtime';
|
|
18
|
-
}
|
|
19
|
-
function hasReactHooks(node) {
|
|
20
|
-
if (!isReactImport(node) || !node.importClause) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
const reactHooks = [
|
|
24
|
-
'useState', 'useEffect', 'useContext', 'useReducer',
|
|
25
|
-
'useCallback', 'useMemo', 'useRef', 'useImperativeHandle',
|
|
26
|
-
'useLayoutEffect', 'useDebugValue', 'useDeferredValue',
|
|
27
|
-
'useTransition', 'useId', 'useSyncExternalStore',
|
|
28
|
-
'useInsertionEffect'
|
|
29
|
-
];
|
|
30
|
-
if (node.importClause.namedBindings && node.importClause.namedBindings.kind === 271) { // NamedImports = 271
|
|
31
|
-
return node.importClause.namedBindings.elements.some((element) => reactHooks.includes(element.name.text));
|
|
32
|
-
}
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
function hasUseClientDirective(sourceFile) {
|
|
36
|
-
// Verifica se a primeira statement é uma expressão "use client"
|
|
37
|
-
if (sourceFile.statements.length === 0)
|
|
38
|
-
return false;
|
|
39
|
-
const firstStatement = sourceFile.statements[0];
|
|
40
|
-
if (firstStatement.kind === 233 && // ExpressionStatement = 233
|
|
41
|
-
firstStatement.expression.kind === 10) { // StringLiteral = 10
|
|
42
|
-
const value = firstStatement.expression.text;
|
|
43
|
-
return value === 'use client';
|
|
44
|
-
}
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
function isBackendFile(fileName) {
|
|
48
|
-
// Verifica se o arquivo está no diretório backend
|
|
49
|
-
return fileName.includes('/backend/') || fileName.includes('\\backend\\');
|
|
50
|
-
}
|
|
51
|
-
function isFrontendFile(fileName) {
|
|
52
|
-
// Verifica se é um arquivo frontend (não backend e dentro de src/web)
|
|
53
|
-
const isInWebDir = fileName.includes('/src/web/') || fileName.includes('\\src\\web\\');
|
|
54
|
-
const isNotBackend = !isBackendFile(fileName);
|
|
55
|
-
const isReactFile = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
56
|
-
return isInWebDir && isNotBackend && isReactFile;
|
|
57
|
-
}
|
|
58
|
-
function createDiagnostic(sourceFile, severity, start = 0, length = 1) {
|
|
59
|
-
const category = severity === 'error' ? 1 : 0; // Error = 1, Warning = 0
|
|
60
|
-
return {
|
|
61
|
-
file: sourceFile,
|
|
62
|
-
start,
|
|
63
|
-
length,
|
|
64
|
-
messageText: 'Arquivos que importam React ou hooks devem começar com "use client"',
|
|
65
|
-
category,
|
|
66
|
-
code: 9001, // Código customizado para o plugin HightJS
|
|
67
|
-
source: 'hightjs'
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function createPlugin(info) {
|
|
71
|
-
const config = { ...defaultConfig, ...info.config };
|
|
72
|
-
if (!config.enabled) {
|
|
73
|
-
return info.languageService;
|
|
74
|
-
}
|
|
75
|
-
const proxy = Object.create(null);
|
|
76
|
-
// Proxy todas as funções do language service
|
|
77
|
-
for (let k of Object.keys(info.languageService)) {
|
|
78
|
-
const x = info.languageService[k];
|
|
79
|
-
proxy[k] = (...args) => x.apply(info.languageService, args);
|
|
80
|
-
}
|
|
81
|
-
// Sobrescreve getSemanticDiagnostics para adicionar nossa validação
|
|
82
|
-
proxy.getSemanticDiagnostics = (fileName) => {
|
|
83
|
-
const originalDiagnostics = info.languageService.getSemanticDiagnostics(fileName);
|
|
84
|
-
// Só valida arquivos frontend
|
|
85
|
-
if (!isFrontendFile(fileName)) {
|
|
86
|
-
return originalDiagnostics;
|
|
87
|
-
}
|
|
88
|
-
const sourceFile = info.languageService.getProgram()?.getSourceFile(fileName);
|
|
89
|
-
if (!sourceFile) {
|
|
90
|
-
return originalDiagnostics;
|
|
91
|
-
}
|
|
92
|
-
let hasReactImportOrHooks = false;
|
|
93
|
-
// Verifica se há imports do React ou hooks
|
|
94
|
-
function visitNode(node) {
|
|
95
|
-
if (node.kind === 270) { // ImportDeclaration = 270
|
|
96
|
-
if (isReactImport(node) || hasReactHooks(node)) {
|
|
97
|
-
hasReactImportOrHooks = true;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
node.forEachChild?.(visitNode);
|
|
101
|
-
}
|
|
102
|
-
visitNode(sourceFile);
|
|
103
|
-
// Se usa React mas não tem "use client", adiciona diagnóstico
|
|
104
|
-
if (hasReactImportOrHooks && !hasUseClientDirective(sourceFile)) {
|
|
105
|
-
const diagnostic = createDiagnostic(sourceFile, config.severity, 0, 1);
|
|
106
|
-
return [...originalDiagnostics, diagnostic];
|
|
107
|
-
}
|
|
108
|
-
return originalDiagnostics;
|
|
109
|
-
};
|
|
110
|
-
return proxy;
|
|
111
|
-
}
|
|
112
|
-
// Para compatibilidade com diferentes versões do TypeScript
|
|
113
|
-
module.exports = createPlugin;
|
package/dist/validation.d.ts
DELETED
|
File without changes
|
package/dist/validation.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|