forlogic-core 1.10.2 → 1.11.0

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.
@@ -0,0 +1,141 @@
1
+ const forlogicTailwindPreset = {
2
+ darkMode: ["class"],
3
+ theme: {
4
+ container: {
5
+ center: true,
6
+ padding: "2rem",
7
+ screens: {
8
+ "2xl": "1400px"
9
+ }
10
+ },
11
+ extend: {
12
+ colors: {
13
+ border: "hsl(var(--border))",
14
+ input: "hsl(var(--input))",
15
+ ring: "hsl(var(--ring))",
16
+ background: "hsl(var(--background))",
17
+ foreground: "hsl(var(--foreground))",
18
+ primary: {
19
+ DEFAULT: "hsl(var(--primary))",
20
+ foreground: "hsl(var(--primary-foreground))",
21
+ hover: "hsl(var(--primary-hover))",
22
+ light: "hsl(var(--primary-light))"
23
+ },
24
+ secondary: {
25
+ DEFAULT: "hsl(var(--secondary))",
26
+ foreground: "hsl(var(--secondary-foreground))",
27
+ hover: "hsl(var(--secondary-hover))"
28
+ },
29
+ destructive: {
30
+ DEFAULT: "hsl(var(--destructive))",
31
+ foreground: "hsl(var(--destructive-foreground))",
32
+ light: "hsl(var(--destructive-light))"
33
+ },
34
+ muted: {
35
+ DEFAULT: "hsl(var(--muted))",
36
+ foreground: "hsl(var(--muted-foreground))"
37
+ },
38
+ accent: {
39
+ DEFAULT: "hsl(var(--accent))",
40
+ foreground: "hsl(var(--accent-foreground))",
41
+ light: "hsl(var(--accent-light))"
42
+ },
43
+ success: {
44
+ DEFAULT: "hsl(var(--success))",
45
+ foreground: "hsl(var(--success-foreground))",
46
+ light: "hsl(var(--success-light))"
47
+ },
48
+ warning: {
49
+ DEFAULT: "hsl(var(--warning))",
50
+ foreground: "hsl(var(--warning-foreground))",
51
+ light: "hsl(var(--warning-light))"
52
+ },
53
+ popover: {
54
+ DEFAULT: "hsl(var(--popover))",
55
+ foreground: "hsl(var(--popover-foreground))"
56
+ },
57
+ card: {
58
+ DEFAULT: "hsl(var(--card))",
59
+ foreground: "hsl(var(--card-foreground))"
60
+ },
61
+ sidebar: {
62
+ DEFAULT: "hsl(var(--sidebar-background))",
63
+ foreground: "hsl(var(--sidebar-foreground))",
64
+ primary: "hsl(var(--sidebar-primary))",
65
+ "primary-foreground": "hsl(var(--sidebar-primary-foreground))",
66
+ accent: "hsl(var(--sidebar-accent))",
67
+ "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
68
+ border: "hsl(var(--sidebar-border))",
69
+ ring: "hsl(var(--sidebar-ring))"
70
+ }
71
+ },
72
+ borderRadius: {
73
+ lg: "var(--radius)",
74
+ md: "calc(var(--radius) - 2px)",
75
+ sm: "calc(var(--radius) - 4px)"
76
+ },
77
+ keyframes: {
78
+ "accordion-down": {
79
+ from: { height: "0" },
80
+ to: { height: "var(--radix-accordion-content-height)" }
81
+ },
82
+ "accordion-up": {
83
+ from: { height: "var(--radix-accordion-content-height)" },
84
+ to: { height: "0" }
85
+ },
86
+ fadeIn: {
87
+ from: { opacity: "0" },
88
+ to: { opacity: "1" }
89
+ },
90
+ slideUp: {
91
+ from: { transform: "translateY(10px)", opacity: "0" },
92
+ to: { transform: "translateY(0)", opacity: "1" }
93
+ },
94
+ slideDown: {
95
+ from: { transform: "translateY(-10px)", opacity: "0" },
96
+ to: { transform: "translateY(0)", opacity: "1" }
97
+ },
98
+ scaleIn: {
99
+ from: { transform: "scale(0.95)", opacity: "0" },
100
+ to: { transform: "scale(1)", opacity: "1" }
101
+ }
102
+ },
103
+ animation: {
104
+ "accordion-down": "accordion-down 0.2s ease-out",
105
+ "accordion-up": "accordion-up 0.2s ease-out",
106
+ "fade-in": "fadeIn 0.5s ease-out",
107
+ "slide-up": "slideUp 0.3s ease-out",
108
+ "slide-down": "slideDown 0.3s ease-out",
109
+ "scale-in": "scaleIn 0.2s ease-out"
110
+ },
111
+ backgroundImage: {
112
+ "gradient-primary": "var(--gradient-primary)",
113
+ "gradient-secondary": "var(--gradient-secondary)",
114
+ "gradient-accent": "var(--gradient-accent)"
115
+ },
116
+ boxShadow: {
117
+ xs: "var(--shadow-xs)",
118
+ sm: "var(--shadow-sm)",
119
+ DEFAULT: "var(--shadow-sm)",
120
+ md: "var(--shadow-md)",
121
+ lg: "var(--shadow-lg)",
122
+ xl: "var(--shadow-xl)",
123
+ "2xl": "var(--shadow-2xl)",
124
+ inner: "var(--shadow-inner)",
125
+ primary: "var(--shadow-primary)",
126
+ none: "none"
127
+ }
128
+ }
129
+ },
130
+ plugins: []
131
+ };
132
+ const forlogicContentPaths = [
133
+ "./pages/**/*.{ts,tsx}",
134
+ "./components/**/*.{ts,tsx}",
135
+ "./app/**/*.{ts,tsx}",
136
+ "./src/**/*.{ts,tsx}",
137
+ "./lib/**/*.{ts,tsx}",
138
+ "./node_modules/forlogic-core/dist/**/*.{js,ts,jsx,tsx}"
139
+ ];
140
+
141
+ export { forlogicContentPaths, forlogicTailwindPreset };
@@ -0,0 +1,144 @@
1
+ 'use strict';
2
+
3
+ const forlogicTailwindPreset = {
4
+ darkMode: ["class"],
5
+ theme: {
6
+ container: {
7
+ center: true,
8
+ padding: "2rem",
9
+ screens: {
10
+ "2xl": "1400px"
11
+ }
12
+ },
13
+ extend: {
14
+ colors: {
15
+ border: "hsl(var(--border))",
16
+ input: "hsl(var(--input))",
17
+ ring: "hsl(var(--ring))",
18
+ background: "hsl(var(--background))",
19
+ foreground: "hsl(var(--foreground))",
20
+ primary: {
21
+ DEFAULT: "hsl(var(--primary))",
22
+ foreground: "hsl(var(--primary-foreground))",
23
+ hover: "hsl(var(--primary-hover))",
24
+ light: "hsl(var(--primary-light))"
25
+ },
26
+ secondary: {
27
+ DEFAULT: "hsl(var(--secondary))",
28
+ foreground: "hsl(var(--secondary-foreground))",
29
+ hover: "hsl(var(--secondary-hover))"
30
+ },
31
+ destructive: {
32
+ DEFAULT: "hsl(var(--destructive))",
33
+ foreground: "hsl(var(--destructive-foreground))",
34
+ light: "hsl(var(--destructive-light))"
35
+ },
36
+ muted: {
37
+ DEFAULT: "hsl(var(--muted))",
38
+ foreground: "hsl(var(--muted-foreground))"
39
+ },
40
+ accent: {
41
+ DEFAULT: "hsl(var(--accent))",
42
+ foreground: "hsl(var(--accent-foreground))",
43
+ light: "hsl(var(--accent-light))"
44
+ },
45
+ success: {
46
+ DEFAULT: "hsl(var(--success))",
47
+ foreground: "hsl(var(--success-foreground))",
48
+ light: "hsl(var(--success-light))"
49
+ },
50
+ warning: {
51
+ DEFAULT: "hsl(var(--warning))",
52
+ foreground: "hsl(var(--warning-foreground))",
53
+ light: "hsl(var(--warning-light))"
54
+ },
55
+ popover: {
56
+ DEFAULT: "hsl(var(--popover))",
57
+ foreground: "hsl(var(--popover-foreground))"
58
+ },
59
+ card: {
60
+ DEFAULT: "hsl(var(--card))",
61
+ foreground: "hsl(var(--card-foreground))"
62
+ },
63
+ sidebar: {
64
+ DEFAULT: "hsl(var(--sidebar-background))",
65
+ foreground: "hsl(var(--sidebar-foreground))",
66
+ primary: "hsl(var(--sidebar-primary))",
67
+ "primary-foreground": "hsl(var(--sidebar-primary-foreground))",
68
+ accent: "hsl(var(--sidebar-accent))",
69
+ "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
70
+ border: "hsl(var(--sidebar-border))",
71
+ ring: "hsl(var(--sidebar-ring))"
72
+ }
73
+ },
74
+ borderRadius: {
75
+ lg: "var(--radius)",
76
+ md: "calc(var(--radius) - 2px)",
77
+ sm: "calc(var(--radius) - 4px)"
78
+ },
79
+ keyframes: {
80
+ "accordion-down": {
81
+ from: { height: "0" },
82
+ to: { height: "var(--radix-accordion-content-height)" }
83
+ },
84
+ "accordion-up": {
85
+ from: { height: "var(--radix-accordion-content-height)" },
86
+ to: { height: "0" }
87
+ },
88
+ fadeIn: {
89
+ from: { opacity: "0" },
90
+ to: { opacity: "1" }
91
+ },
92
+ slideUp: {
93
+ from: { transform: "translateY(10px)", opacity: "0" },
94
+ to: { transform: "translateY(0)", opacity: "1" }
95
+ },
96
+ slideDown: {
97
+ from: { transform: "translateY(-10px)", opacity: "0" },
98
+ to: { transform: "translateY(0)", opacity: "1" }
99
+ },
100
+ scaleIn: {
101
+ from: { transform: "scale(0.95)", opacity: "0" },
102
+ to: { transform: "scale(1)", opacity: "1" }
103
+ }
104
+ },
105
+ animation: {
106
+ "accordion-down": "accordion-down 0.2s ease-out",
107
+ "accordion-up": "accordion-up 0.2s ease-out",
108
+ "fade-in": "fadeIn 0.5s ease-out",
109
+ "slide-up": "slideUp 0.3s ease-out",
110
+ "slide-down": "slideDown 0.3s ease-out",
111
+ "scale-in": "scaleIn 0.2s ease-out"
112
+ },
113
+ backgroundImage: {
114
+ "gradient-primary": "var(--gradient-primary)",
115
+ "gradient-secondary": "var(--gradient-secondary)",
116
+ "gradient-accent": "var(--gradient-accent)"
117
+ },
118
+ boxShadow: {
119
+ xs: "var(--shadow-xs)",
120
+ sm: "var(--shadow-sm)",
121
+ DEFAULT: "var(--shadow-sm)",
122
+ md: "var(--shadow-md)",
123
+ lg: "var(--shadow-lg)",
124
+ xl: "var(--shadow-xl)",
125
+ "2xl": "var(--shadow-2xl)",
126
+ inner: "var(--shadow-inner)",
127
+ primary: "var(--shadow-primary)",
128
+ none: "none"
129
+ }
130
+ }
131
+ },
132
+ plugins: []
133
+ };
134
+ const forlogicContentPaths = [
135
+ "./pages/**/*.{ts,tsx}",
136
+ "./components/**/*.{ts,tsx}",
137
+ "./app/**/*.{ts,tsx}",
138
+ "./src/**/*.{ts,tsx}",
139
+ "./lib/**/*.{ts,tsx}",
140
+ "./node_modules/forlogic-core/dist/**/*.{js,ts,jsx,tsx}"
141
+ ];
142
+
143
+ exports.forlogicContentPaths = forlogicContentPaths;
144
+ exports.forlogicTailwindPreset = forlogicTailwindPreset;
@@ -0,0 +1,204 @@
1
+ const DEFAULT_SCRIPT_SRC = [
2
+ "'self'",
3
+ "https://cdn.gpteng.co",
4
+ "https://cdn.tailwindcss.com"
5
+ ];
6
+ const DEFAULT_STYLE_SRC = [
7
+ "'self'",
8
+ "https://fonts.googleapis.com"
9
+ ];
10
+ const DEFAULT_CONNECT_SRC = [
11
+ "'self'"
12
+ ];
13
+ const DEFAULT_FONT_SRC = [
14
+ "'self'",
15
+ "data:",
16
+ "https://fonts.gstatic.com"
17
+ ];
18
+ const DEFAULT_IMG_SRC = [
19
+ "'self'",
20
+ "data:",
21
+ "https:"
22
+ ];
23
+ const DEFAULT_FRAME_ANCESTORS = [
24
+ "'self'",
25
+ "https://lovableproject.com",
26
+ "https://*.lovableproject.com",
27
+ "https://lovable.dev"
28
+ ];
29
+ function generateCSPPolicy(isDev, options = {}) {
30
+ const {
31
+ supabaseUrls = [],
32
+ additionalScriptSrc = [],
33
+ additionalStyleSrc = [],
34
+ additionalConnectSrc = [],
35
+ cspReportUri,
36
+ enableTrustedTypes = true,
37
+ upgradeInsecureRequests = true
38
+ } = options;
39
+ const connectSrc = [
40
+ ...DEFAULT_CONNECT_SRC,
41
+ ...supabaseUrls,
42
+ ...additionalConnectSrc,
43
+ // Localhost para desenvolvimento
44
+ ...isDev ? ["http://localhost:*", "ws://localhost:*"] : []
45
+ ];
46
+ const scriptSrc = [
47
+ ...DEFAULT_SCRIPT_SRC,
48
+ ...additionalScriptSrc
49
+ ];
50
+ const styleSrc = [
51
+ ...DEFAULT_STYLE_SRC,
52
+ ...additionalStyleSrc
53
+ ];
54
+ const basePolicy = [
55
+ `default-src 'self'`,
56
+ `img-src ${DEFAULT_IMG_SRC.join(" ")}`,
57
+ `font-src ${DEFAULT_FONT_SRC.join(" ")}`,
58
+ `connect-src ${connectSrc.join(" ")}`,
59
+ `frame-ancestors ${DEFAULT_FRAME_ANCESTORS.join(" ")}`,
60
+ `base-uri 'self'`,
61
+ `form-action 'self'`,
62
+ `object-src 'none'`,
63
+ `media-src 'self'`,
64
+ `child-src 'none'`,
65
+ `worker-src 'self'`,
66
+ `manifest-src 'self'`
67
+ ];
68
+ if (upgradeInsecureRequests && !isDev) {
69
+ basePolicy.push("upgrade-insecure-requests");
70
+ }
71
+ if (isDev) {
72
+ return [
73
+ ...basePolicy,
74
+ `script-src ${scriptSrc.join(" ")} 'unsafe-inline' 'unsafe-eval'`,
75
+ `style-src ${styleSrc.join(" ")} 'unsafe-inline'`,
76
+ ...cspReportUri ? [`report-uri ${cspReportUri}`] : []
77
+ ].join("; ");
78
+ } else {
79
+ const prodPolicy = [
80
+ ...basePolicy,
81
+ `script-src ${scriptSrc.join(" ")}`,
82
+ `style-src ${styleSrc.join(" ")}`
83
+ ];
84
+ if (enableTrustedTypes) {
85
+ prodPolicy.push("require-trusted-types-for 'script'");
86
+ prodPolicy.push("trusted-types default");
87
+ }
88
+ if (cspReportUri) {
89
+ prodPolicy.push(`report-uri ${cspReportUri}`);
90
+ }
91
+ return prodPolicy.join("; ");
92
+ }
93
+ }
94
+
95
+ const DEFAULT_TRUSTED_ORIGINS = [
96
+ "https://lovableproject.com",
97
+ "https://lovable.dev"
98
+ ];
99
+ const DEV_TRUSTED_ORIGINS = [
100
+ "http://localhost:8080",
101
+ "http://localhost:3000",
102
+ "http://localhost:5173"
103
+ ];
104
+ function isOriginTrusted(origin, trustedOrigins) {
105
+ return trustedOrigins.some((trusted) => {
106
+ if (trusted.includes("*.")) {
107
+ const pattern = trusted.replace("*.", ".*\\.");
108
+ return new RegExp(pattern).test(origin);
109
+ }
110
+ return origin === trusted || origin.startsWith(trusted);
111
+ });
112
+ }
113
+ function createSecurityHeadersPlugin(isDev, options = {}) {
114
+ const { trustedOrigins = [] } = options;
115
+ const allTrustedOrigins = [
116
+ ...DEFAULT_TRUSTED_ORIGINS,
117
+ ...trustedOrigins,
118
+ ...isDev ? DEV_TRUSTED_ORIGINS : []
119
+ ];
120
+ const cspPolicy = generateCSPPolicy(isDev, options);
121
+ return {
122
+ name: "forlogic-security-headers",
123
+ configureServer(server) {
124
+ server.middlewares.use((req, res, next) => {
125
+ const origin = req.headers.origin;
126
+ if (origin && isOriginTrusted(origin, allTrustedOrigins)) {
127
+ res.setHeader("Access-Control-Allow-Origin", origin);
128
+ res.setHeader("Access-Control-Allow-Credentials", "true");
129
+ res.setHeader(
130
+ "Access-Control-Allow-Methods",
131
+ "GET, POST, PUT, PATCH, DELETE, OPTIONS"
132
+ );
133
+ res.setHeader(
134
+ "Access-Control-Allow-Headers",
135
+ "authorization, x-client-info, apikey, content-type, x-csrf-token, x-nonce"
136
+ );
137
+ res.setHeader("Access-Control-Max-Age", "86400");
138
+ res.setHeader("Vary", "Origin");
139
+ } else if (origin) {
140
+ console.warn(
141
+ `\u{1F6A8} CORS BLOCKED: Untrusted origin attempted access: ${origin}`
142
+ );
143
+ }
144
+ res.setHeader(
145
+ "Strict-Transport-Security",
146
+ "max-age=31536000; includeSubDomains; preload"
147
+ );
148
+ res.setHeader("X-Content-Type-Options", "nosniff");
149
+ res.setHeader("X-Frame-Options", "DENY");
150
+ res.setHeader("X-XSS-Protection", "1; mode=block");
151
+ res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
152
+ res.setHeader(
153
+ "Permissions-Policy",
154
+ "camera=(), microphone=(), geolocation=(), fullscreen=(self), payment=(), display-capture=()"
155
+ );
156
+ res.setHeader("Content-Security-Policy", cspPolicy);
157
+ next();
158
+ });
159
+ }
160
+ };
161
+ }
162
+
163
+ function createForlogicViteConfig(options = {}) {
164
+ const {
165
+ srcAlias = "@",
166
+ libAlias = "forlogic-core",
167
+ security = {},
168
+ server = {},
169
+ build = {},
170
+ additionalPlugins = [],
171
+ disableSecurity = false
172
+ } = options;
173
+ return (isDev) => {
174
+ const plugins = [...additionalPlugins];
175
+ if (!disableSecurity) {
176
+ plugins.push(createSecurityHeadersPlugin(isDev, security));
177
+ }
178
+ return {
179
+ server: {
180
+ host: server.host ?? "::",
181
+ port: server.port ?? 8080
182
+ },
183
+ resolve: {
184
+ alias: {
185
+ [srcAlias]: "./src",
186
+ [libAlias]: "./lib",
187
+ "/assets": "./lib/assets"
188
+ }
189
+ },
190
+ publicDir: false,
191
+ esbuild: {
192
+ sourcemap: build.sourcemap ?? true,
193
+ target: "es2020"
194
+ },
195
+ build: {
196
+ chunkSizeWarningLimit: build.chunkSizeWarningLimit ?? 4e3
197
+ },
198
+ plugins
199
+ };
200
+ };
201
+ }
202
+ const defaultForlogicViteConfig = createForlogicViteConfig();
203
+
204
+ export { createForlogicViteConfig, createSecurityHeadersPlugin, defaultForlogicViteConfig, generateCSPPolicy };
@@ -0,0 +1,209 @@
1
+ 'use strict';
2
+
3
+ const DEFAULT_SCRIPT_SRC = [
4
+ "'self'",
5
+ "https://cdn.gpteng.co",
6
+ "https://cdn.tailwindcss.com"
7
+ ];
8
+ const DEFAULT_STYLE_SRC = [
9
+ "'self'",
10
+ "https://fonts.googleapis.com"
11
+ ];
12
+ const DEFAULT_CONNECT_SRC = [
13
+ "'self'"
14
+ ];
15
+ const DEFAULT_FONT_SRC = [
16
+ "'self'",
17
+ "data:",
18
+ "https://fonts.gstatic.com"
19
+ ];
20
+ const DEFAULT_IMG_SRC = [
21
+ "'self'",
22
+ "data:",
23
+ "https:"
24
+ ];
25
+ const DEFAULT_FRAME_ANCESTORS = [
26
+ "'self'",
27
+ "https://lovableproject.com",
28
+ "https://*.lovableproject.com",
29
+ "https://lovable.dev"
30
+ ];
31
+ function generateCSPPolicy(isDev, options = {}) {
32
+ const {
33
+ supabaseUrls = [],
34
+ additionalScriptSrc = [],
35
+ additionalStyleSrc = [],
36
+ additionalConnectSrc = [],
37
+ cspReportUri,
38
+ enableTrustedTypes = true,
39
+ upgradeInsecureRequests = true
40
+ } = options;
41
+ const connectSrc = [
42
+ ...DEFAULT_CONNECT_SRC,
43
+ ...supabaseUrls,
44
+ ...additionalConnectSrc,
45
+ // Localhost para desenvolvimento
46
+ ...isDev ? ["http://localhost:*", "ws://localhost:*"] : []
47
+ ];
48
+ const scriptSrc = [
49
+ ...DEFAULT_SCRIPT_SRC,
50
+ ...additionalScriptSrc
51
+ ];
52
+ const styleSrc = [
53
+ ...DEFAULT_STYLE_SRC,
54
+ ...additionalStyleSrc
55
+ ];
56
+ const basePolicy = [
57
+ `default-src 'self'`,
58
+ `img-src ${DEFAULT_IMG_SRC.join(" ")}`,
59
+ `font-src ${DEFAULT_FONT_SRC.join(" ")}`,
60
+ `connect-src ${connectSrc.join(" ")}`,
61
+ `frame-ancestors ${DEFAULT_FRAME_ANCESTORS.join(" ")}`,
62
+ `base-uri 'self'`,
63
+ `form-action 'self'`,
64
+ `object-src 'none'`,
65
+ `media-src 'self'`,
66
+ `child-src 'none'`,
67
+ `worker-src 'self'`,
68
+ `manifest-src 'self'`
69
+ ];
70
+ if (upgradeInsecureRequests && !isDev) {
71
+ basePolicy.push("upgrade-insecure-requests");
72
+ }
73
+ if (isDev) {
74
+ return [
75
+ ...basePolicy,
76
+ `script-src ${scriptSrc.join(" ")} 'unsafe-inline' 'unsafe-eval'`,
77
+ `style-src ${styleSrc.join(" ")} 'unsafe-inline'`,
78
+ ...cspReportUri ? [`report-uri ${cspReportUri}`] : []
79
+ ].join("; ");
80
+ } else {
81
+ const prodPolicy = [
82
+ ...basePolicy,
83
+ `script-src ${scriptSrc.join(" ")}`,
84
+ `style-src ${styleSrc.join(" ")}`
85
+ ];
86
+ if (enableTrustedTypes) {
87
+ prodPolicy.push("require-trusted-types-for 'script'");
88
+ prodPolicy.push("trusted-types default");
89
+ }
90
+ if (cspReportUri) {
91
+ prodPolicy.push(`report-uri ${cspReportUri}`);
92
+ }
93
+ return prodPolicy.join("; ");
94
+ }
95
+ }
96
+
97
+ const DEFAULT_TRUSTED_ORIGINS = [
98
+ "https://lovableproject.com",
99
+ "https://lovable.dev"
100
+ ];
101
+ const DEV_TRUSTED_ORIGINS = [
102
+ "http://localhost:8080",
103
+ "http://localhost:3000",
104
+ "http://localhost:5173"
105
+ ];
106
+ function isOriginTrusted(origin, trustedOrigins) {
107
+ return trustedOrigins.some((trusted) => {
108
+ if (trusted.includes("*.")) {
109
+ const pattern = trusted.replace("*.", ".*\\.");
110
+ return new RegExp(pattern).test(origin);
111
+ }
112
+ return origin === trusted || origin.startsWith(trusted);
113
+ });
114
+ }
115
+ function createSecurityHeadersPlugin(isDev, options = {}) {
116
+ const { trustedOrigins = [] } = options;
117
+ const allTrustedOrigins = [
118
+ ...DEFAULT_TRUSTED_ORIGINS,
119
+ ...trustedOrigins,
120
+ ...isDev ? DEV_TRUSTED_ORIGINS : []
121
+ ];
122
+ const cspPolicy = generateCSPPolicy(isDev, options);
123
+ return {
124
+ name: "forlogic-security-headers",
125
+ configureServer(server) {
126
+ server.middlewares.use((req, res, next) => {
127
+ const origin = req.headers.origin;
128
+ if (origin && isOriginTrusted(origin, allTrustedOrigins)) {
129
+ res.setHeader("Access-Control-Allow-Origin", origin);
130
+ res.setHeader("Access-Control-Allow-Credentials", "true");
131
+ res.setHeader(
132
+ "Access-Control-Allow-Methods",
133
+ "GET, POST, PUT, PATCH, DELETE, OPTIONS"
134
+ );
135
+ res.setHeader(
136
+ "Access-Control-Allow-Headers",
137
+ "authorization, x-client-info, apikey, content-type, x-csrf-token, x-nonce"
138
+ );
139
+ res.setHeader("Access-Control-Max-Age", "86400");
140
+ res.setHeader("Vary", "Origin");
141
+ } else if (origin) {
142
+ console.warn(
143
+ `\u{1F6A8} CORS BLOCKED: Untrusted origin attempted access: ${origin}`
144
+ );
145
+ }
146
+ res.setHeader(
147
+ "Strict-Transport-Security",
148
+ "max-age=31536000; includeSubDomains; preload"
149
+ );
150
+ res.setHeader("X-Content-Type-Options", "nosniff");
151
+ res.setHeader("X-Frame-Options", "DENY");
152
+ res.setHeader("X-XSS-Protection", "1; mode=block");
153
+ res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
154
+ res.setHeader(
155
+ "Permissions-Policy",
156
+ "camera=(), microphone=(), geolocation=(), fullscreen=(self), payment=(), display-capture=()"
157
+ );
158
+ res.setHeader("Content-Security-Policy", cspPolicy);
159
+ next();
160
+ });
161
+ }
162
+ };
163
+ }
164
+
165
+ function createForlogicViteConfig(options = {}) {
166
+ const {
167
+ srcAlias = "@",
168
+ libAlias = "forlogic-core",
169
+ security = {},
170
+ server = {},
171
+ build = {},
172
+ additionalPlugins = [],
173
+ disableSecurity = false
174
+ } = options;
175
+ return (isDev) => {
176
+ const plugins = [...additionalPlugins];
177
+ if (!disableSecurity) {
178
+ plugins.push(createSecurityHeadersPlugin(isDev, security));
179
+ }
180
+ return {
181
+ server: {
182
+ host: server.host ?? "::",
183
+ port: server.port ?? 8080
184
+ },
185
+ resolve: {
186
+ alias: {
187
+ [srcAlias]: "./src",
188
+ [libAlias]: "./lib",
189
+ "/assets": "./lib/assets"
190
+ }
191
+ },
192
+ publicDir: false,
193
+ esbuild: {
194
+ sourcemap: build.sourcemap ?? true,
195
+ target: "es2020"
196
+ },
197
+ build: {
198
+ chunkSizeWarningLimit: build.chunkSizeWarningLimit ?? 4e3
199
+ },
200
+ plugins
201
+ };
202
+ };
203
+ }
204
+ const defaultForlogicViteConfig = createForlogicViteConfig();
205
+
206
+ exports.createForlogicViteConfig = createForlogicViteConfig;
207
+ exports.createSecurityHeadersPlugin = createSecurityHeadersPlugin;
208
+ exports.defaultForlogicViteConfig = defaultForlogicViteConfig;
209
+ exports.generateCSPPolicy = generateCSPPolicy;