@harpy-js/core 0.5.6 → 0.5.7

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.
File without changes
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ describe('Canonical Redirect Logic', () => {
3
+ function shouldRedirect(options) {
4
+ const { host, protocol, mainDomain, enforceHttps = true, redirectWww = true } = options;
5
+ const normalizedHost = host.replace(/:\d+$/, '');
6
+ if (normalizedHost === 'localhost' || normalizedHost === '127.0.0.1' || normalizedHost === '0.0.0.0') {
7
+ return { shouldRedirect: false };
8
+ }
9
+ const proto = protocol;
10
+ const isHttp = enforceHttps && proto !== 'https';
11
+ const isWww = redirectWww && normalizedHost.startsWith('www.');
12
+ const hostMismatch = mainDomain && normalizedHost !== mainDomain && normalizedHost !== `www.${mainDomain}`;
13
+ if (isHttp || isWww || hostMismatch) {
14
+ const targetHost = mainDomain ? mainDomain : normalizedHost.replace(/^www\./, '');
15
+ const targetProto = enforceHttps ? 'https' : proto;
16
+ const targetUrl = `${targetProto}://${targetHost}/`;
17
+ return { shouldRedirect: true, targetUrl };
18
+ }
19
+ return { shouldRedirect: false };
20
+ }
21
+ describe('HTTP to HTTPS redirect', () => {
22
+ it('should redirect http://harpyjs.org to https://harpyjs.org', () => {
23
+ const result = shouldRedirect({
24
+ host: 'harpyjs.org',
25
+ protocol: 'http',
26
+ mainDomain: 'harpyjs.org',
27
+ enforceHttps: true,
28
+ redirectWww: true,
29
+ });
30
+ expect(result.shouldRedirect).toBe(true);
31
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
32
+ });
33
+ it('should not redirect https://harpyjs.org', () => {
34
+ const result = shouldRedirect({
35
+ host: 'harpyjs.org',
36
+ protocol: 'https',
37
+ mainDomain: 'harpyjs.org',
38
+ enforceHttps: true,
39
+ redirectWww: true,
40
+ });
41
+ expect(result.shouldRedirect).toBe(false);
42
+ });
43
+ });
44
+ describe('WWW to non-WWW redirect', () => {
45
+ it('should redirect www.harpyjs.org to harpyjs.org', () => {
46
+ const result = shouldRedirect({
47
+ host: 'www.harpyjs.org',
48
+ protocol: 'https',
49
+ mainDomain: 'harpyjs.org',
50
+ enforceHttps: true,
51
+ redirectWww: true,
52
+ });
53
+ expect(result.shouldRedirect).toBe(true);
54
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
55
+ });
56
+ it('should not redirect when redirectWww is false', () => {
57
+ const result = shouldRedirect({
58
+ host: 'www.harpyjs.org',
59
+ protocol: 'https',
60
+ mainDomain: 'harpyjs.org',
61
+ enforceHttps: true,
62
+ redirectWww: false,
63
+ });
64
+ expect(result.shouldRedirect).toBe(false);
65
+ });
66
+ });
67
+ describe('Combined redirects', () => {
68
+ it('should redirect http://www.harpyjs.org to https://harpyjs.org', () => {
69
+ const result = shouldRedirect({
70
+ host: 'www.harpyjs.org',
71
+ protocol: 'http',
72
+ mainDomain: 'harpyjs.org',
73
+ enforceHttps: true,
74
+ redirectWww: true,
75
+ });
76
+ expect(result.shouldRedirect).toBe(true);
77
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
78
+ });
79
+ });
80
+ describe('Localhost exemption', () => {
81
+ it('should not redirect localhost', () => {
82
+ const result = shouldRedirect({
83
+ host: 'localhost',
84
+ protocol: 'http',
85
+ mainDomain: 'harpyjs.org',
86
+ enforceHttps: true,
87
+ redirectWww: true,
88
+ });
89
+ expect(result.shouldRedirect).toBe(false);
90
+ });
91
+ it('should not redirect 127.0.0.1', () => {
92
+ const result = shouldRedirect({
93
+ host: '127.0.0.1',
94
+ protocol: 'http',
95
+ mainDomain: 'harpyjs.org',
96
+ enforceHttps: true,
97
+ redirectWww: true,
98
+ });
99
+ expect(result.shouldRedirect).toBe(false);
100
+ });
101
+ it('should not redirect localhost:3000', () => {
102
+ const result = shouldRedirect({
103
+ host: 'localhost:3000',
104
+ protocol: 'http',
105
+ mainDomain: 'harpyjs.org',
106
+ enforceHttps: true,
107
+ redirectWww: true,
108
+ });
109
+ expect(result.shouldRedirect).toBe(false);
110
+ });
111
+ });
112
+ describe('Domain enforcement', () => {
113
+ it('should redirect different domain to mainDomain', () => {
114
+ const result = shouldRedirect({
115
+ host: 'example.com',
116
+ protocol: 'https',
117
+ mainDomain: 'harpyjs.org',
118
+ enforceHttps: true,
119
+ redirectWww: true,
120
+ });
121
+ expect(result.shouldRedirect).toBe(true);
122
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
123
+ });
124
+ it('should not redirect when host matches mainDomain', () => {
125
+ const result = shouldRedirect({
126
+ host: 'harpyjs.org',
127
+ protocol: 'https',
128
+ mainDomain: 'harpyjs.org',
129
+ enforceHttps: true,
130
+ redirectWww: true,
131
+ });
132
+ expect(result.shouldRedirect).toBe(false);
133
+ });
134
+ });
135
+ describe('Configuration variations', () => {
136
+ it('should not redirect http when enforceHttps is false', () => {
137
+ const result = shouldRedirect({
138
+ host: 'harpyjs.org',
139
+ protocol: 'http',
140
+ mainDomain: 'harpyjs.org',
141
+ enforceHttps: false,
142
+ redirectWww: true,
143
+ });
144
+ expect(result.shouldRedirect).toBe(false);
145
+ });
146
+ it('should work without mainDomain specified', () => {
147
+ const result = shouldRedirect({
148
+ host: 'www.example.com',
149
+ protocol: 'https',
150
+ enforceHttps: true,
151
+ redirectWww: true,
152
+ });
153
+ expect(result.shouldRedirect).toBe(true);
154
+ expect(result.targetUrl).toBe('https://example.com/');
155
+ });
156
+ });
157
+ });
@@ -5,6 +5,10 @@ export interface HarpyAppOptions {
5
5
  distDir?: string;
6
6
  publicDir?: string;
7
7
  errorPages?: ErrorPagesConfig;
8
+ enforceRedirects?: boolean;
9
+ mainDomain?: string;
10
+ enforceHttps?: boolean;
11
+ redirectWww?: boolean;
8
12
  }
9
13
  export declare function configureHarpyApp(app: NestFastifyApplication, opts?: HarpyAppOptions): Promise<void>;
10
14
  export declare function setupHarpyApp(app: NestFastifyApplication, opts?: HarpyAppOptions): Promise<void>;
@@ -65,6 +65,35 @@ async function configureHarpyApp(app, opts = {}) {
65
65
  (0, jsx_engine_1.withJsxEngine)(app, layout);
66
66
  }
67
67
  const fastify = app.getHttpAdapter().getInstance();
68
+ const { enforceRedirects = false, mainDomain, enforceHttps = true, redirectWww = true, } = opts;
69
+ if (enforceRedirects && (mainDomain || enforceHttps || redirectWww)) {
70
+ fastify.addHook('onRequest', (req, reply, done) => {
71
+ try {
72
+ const hostHeader = (req.headers && (req.headers.host || '')).toString();
73
+ const normalizedHost = hostHeader.replace(/:\d+$/, '');
74
+ if (normalizedHost === 'localhost' || normalizedHost === '127.0.0.1' || normalizedHost === '0.0.0.0') {
75
+ done();
76
+ return;
77
+ }
78
+ const forwardedProto = (req.headers['x-forwarded-proto'] || '').toString();
79
+ const proto = forwardedProto || (req.raw && req.raw.socket && req.raw.socket.encrypted ? 'https' : 'http');
80
+ const isHttp = enforceHttps && proto !== 'https';
81
+ const isWww = redirectWww && normalizedHost.startsWith('www.');
82
+ const hostMismatch = mainDomain && normalizedHost !== mainDomain && normalizedHost !== `www.${mainDomain}`;
83
+ if (isHttp || isWww || hostMismatch) {
84
+ const targetHost = mainDomain ? mainDomain : normalizedHost.replace(/^www\./, '');
85
+ const targetProto = enforceHttps ? 'https' : proto;
86
+ const targetUrl = `${targetProto}://${targetHost}${req.url}`;
87
+ reply.status(301).header('Cache-Control', 'public, max-age=31536000').redirect(targetUrl);
88
+ return;
89
+ }
90
+ }
91
+ catch (e) {
92
+ console.warn('[harpy-core] redirect hook error', e);
93
+ }
94
+ done();
95
+ });
96
+ }
68
97
  const NotFoundComponent = errorPages?.["404"] || default_404_1.default;
69
98
  fastify.setErrorHandler((error, request, reply) => {
70
99
  if (error?.statusCode === 404 || reply.statusCode === 404) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harpy-js/core",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
4
  "description": "Harpy - A powerful NestJS + React/JSX SSR framework with automatic hydration and i18n support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Unit tests for canonical redirect logic
3
+ */
4
+
5
+ describe('Canonical Redirect Logic', () => {
6
+ // Simulate the redirect logic from app-setup.ts
7
+ function shouldRedirect(options: {
8
+ host: string;
9
+ protocol: string;
10
+ mainDomain?: string;
11
+ enforceHttps?: boolean;
12
+ redirectWww?: boolean;
13
+ }): { shouldRedirect: boolean; targetUrl?: string } {
14
+ const { host, protocol, mainDomain, enforceHttps = true, redirectWww = true } = options;
15
+
16
+ const normalizedHost = host.replace(/:\d+$/, '');
17
+
18
+ // Skip redirects for localhost/127.0.0.1
19
+ if (normalizedHost === 'localhost' || normalizedHost === '127.0.0.1' || normalizedHost === '0.0.0.0') {
20
+ return { shouldRedirect: false };
21
+ }
22
+
23
+ const proto = protocol;
24
+
25
+ // Decide whether to redirect
26
+ const isHttp = enforceHttps && proto !== 'https';
27
+ const isWww = redirectWww && normalizedHost.startsWith('www.');
28
+ const hostMismatch = mainDomain && normalizedHost !== mainDomain && normalizedHost !== `www.${mainDomain}`;
29
+
30
+ if (isHttp || isWww || hostMismatch) {
31
+ const targetHost = mainDomain ? mainDomain : normalizedHost.replace(/^www\./, '');
32
+ const targetProto = enforceHttps ? 'https' : proto;
33
+ const targetUrl = `${targetProto}://${targetHost}/`;
34
+
35
+ return { shouldRedirect: true, targetUrl };
36
+ }
37
+
38
+ return { shouldRedirect: false };
39
+ }
40
+
41
+ describe('HTTP to HTTPS redirect', () => {
42
+ it('should redirect http://harpyjs.org to https://harpyjs.org', () => {
43
+ const result = shouldRedirect({
44
+ host: 'harpyjs.org',
45
+ protocol: 'http',
46
+ mainDomain: 'harpyjs.org',
47
+ enforceHttps: true,
48
+ redirectWww: true,
49
+ });
50
+
51
+ expect(result.shouldRedirect).toBe(true);
52
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
53
+ });
54
+
55
+ it('should not redirect https://harpyjs.org', () => {
56
+ const result = shouldRedirect({
57
+ host: 'harpyjs.org',
58
+ protocol: 'https',
59
+ mainDomain: 'harpyjs.org',
60
+ enforceHttps: true,
61
+ redirectWww: true,
62
+ });
63
+
64
+ expect(result.shouldRedirect).toBe(false);
65
+ });
66
+ });
67
+
68
+ describe('WWW to non-WWW redirect', () => {
69
+ it('should redirect www.harpyjs.org to harpyjs.org', () => {
70
+ const result = shouldRedirect({
71
+ host: 'www.harpyjs.org',
72
+ protocol: 'https',
73
+ mainDomain: 'harpyjs.org',
74
+ enforceHttps: true,
75
+ redirectWww: true,
76
+ });
77
+
78
+ expect(result.shouldRedirect).toBe(true);
79
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
80
+ });
81
+
82
+ it('should not redirect when redirectWww is false', () => {
83
+ const result = shouldRedirect({
84
+ host: 'www.harpyjs.org',
85
+ protocol: 'https',
86
+ mainDomain: 'harpyjs.org',
87
+ enforceHttps: true,
88
+ redirectWww: false,
89
+ });
90
+
91
+ expect(result.shouldRedirect).toBe(false);
92
+ });
93
+ });
94
+
95
+ describe('Combined redirects', () => {
96
+ it('should redirect http://www.harpyjs.org to https://harpyjs.org', () => {
97
+ const result = shouldRedirect({
98
+ host: 'www.harpyjs.org',
99
+ protocol: 'http',
100
+ mainDomain: 'harpyjs.org',
101
+ enforceHttps: true,
102
+ redirectWww: true,
103
+ });
104
+
105
+ expect(result.shouldRedirect).toBe(true);
106
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
107
+ });
108
+ });
109
+
110
+ describe('Localhost exemption', () => {
111
+ it('should not redirect localhost', () => {
112
+ const result = shouldRedirect({
113
+ host: 'localhost',
114
+ protocol: 'http',
115
+ mainDomain: 'harpyjs.org',
116
+ enforceHttps: true,
117
+ redirectWww: true,
118
+ });
119
+
120
+ expect(result.shouldRedirect).toBe(false);
121
+ });
122
+
123
+ it('should not redirect 127.0.0.1', () => {
124
+ const result = shouldRedirect({
125
+ host: '127.0.0.1',
126
+ protocol: 'http',
127
+ mainDomain: 'harpyjs.org',
128
+ enforceHttps: true,
129
+ redirectWww: true,
130
+ });
131
+
132
+ expect(result.shouldRedirect).toBe(false);
133
+ });
134
+
135
+ it('should not redirect localhost:3000', () => {
136
+ const result = shouldRedirect({
137
+ host: 'localhost:3000',
138
+ protocol: 'http',
139
+ mainDomain: 'harpyjs.org',
140
+ enforceHttps: true,
141
+ redirectWww: true,
142
+ });
143
+
144
+ expect(result.shouldRedirect).toBe(false);
145
+ });
146
+ });
147
+
148
+ describe('Domain enforcement', () => {
149
+ it('should redirect different domain to mainDomain', () => {
150
+ const result = shouldRedirect({
151
+ host: 'example.com',
152
+ protocol: 'https',
153
+ mainDomain: 'harpyjs.org',
154
+ enforceHttps: true,
155
+ redirectWww: true,
156
+ });
157
+
158
+ expect(result.shouldRedirect).toBe(true);
159
+ expect(result.targetUrl).toBe('https://harpyjs.org/');
160
+ });
161
+
162
+ it('should not redirect when host matches mainDomain', () => {
163
+ const result = shouldRedirect({
164
+ host: 'harpyjs.org',
165
+ protocol: 'https',
166
+ mainDomain: 'harpyjs.org',
167
+ enforceHttps: true,
168
+ redirectWww: true,
169
+ });
170
+
171
+ expect(result.shouldRedirect).toBe(false);
172
+ });
173
+ });
174
+
175
+ describe('Configuration variations', () => {
176
+ it('should not redirect http when enforceHttps is false', () => {
177
+ const result = shouldRedirect({
178
+ host: 'harpyjs.org',
179
+ protocol: 'http',
180
+ mainDomain: 'harpyjs.org',
181
+ enforceHttps: false,
182
+ redirectWww: true,
183
+ });
184
+
185
+ expect(result.shouldRedirect).toBe(false);
186
+ });
187
+
188
+ it('should work without mainDomain specified', () => {
189
+ const result = shouldRedirect({
190
+ host: 'www.example.com',
191
+ protocol: 'https',
192
+ enforceHttps: true,
193
+ redirectWww: true,
194
+ });
195
+
196
+ expect(result.shouldRedirect).toBe(true);
197
+ expect(result.targetUrl).toBe('https://example.com/');
198
+ });
199
+ });
200
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-setup.js","sourceRoot":"","sources":["app-setup.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,16 @@ export interface HarpyAppOptions {
38
38
  publicDir?: string;
39
39
  /** Custom error pages for different HTTP status codes */
40
40
  errorPages?: ErrorPagesConfig;
41
+ /**
42
+ * Optional redirect settings. When `enforceRedirects` is true (default false)
43
+ * Harpy will register a Fastify `onRequest` hook to redirect requests to
44
+ * the canonical domain and HTTPS. Configure `mainDomain` to your primary
45
+ * host (e.g. `harpyjs.org`).
46
+ */
47
+ enforceRedirects?: boolean;
48
+ mainDomain?: string;
49
+ enforceHttps?: boolean;
50
+ redirectWww?: boolean;
41
51
  }
42
52
 
43
53
  /**
@@ -61,6 +71,60 @@ export async function configureHarpyApp(
61
71
 
62
72
  const fastify = app.getHttpAdapter().getInstance();
63
73
 
74
+ // Optional redirects to canonical domain / HTTPS
75
+ const {
76
+ enforceRedirects = false,
77
+ mainDomain,
78
+ enforceHttps = true,
79
+ redirectWww = true,
80
+ } = opts as HarpyAppOptions;
81
+
82
+ if (enforceRedirects && (mainDomain || enforceHttps || redirectWww)) {
83
+ // Register early hook to redirect incoming requests to the canonical URL
84
+ // This keeps redirect handling in Harpy core so consumers can opt-in.
85
+ // Uses x-forwarded-proto when behind proxies (Vercel, Cloudflare)
86
+ // and falls back to socket encryption detection.
87
+ // NOTE: Make sure your proxy forwards `x-forwarded-proto`.
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ fastify.addHook('onRequest', (req: any, reply: any, done: any) => {
90
+ try {
91
+ const hostHeader = (req.headers && (req.headers.host || '')).toString();
92
+ const normalizedHost = hostHeader.replace(/:\d+$/, '');
93
+
94
+ // Skip redirects for localhost/127.0.0.1 (local development)
95
+ if (normalizedHost === 'localhost' || normalizedHost === '127.0.0.1' || normalizedHost === '0.0.0.0') {
96
+ done();
97
+ return;
98
+ }
99
+
100
+ const forwardedProto = (req.headers['x-forwarded-proto'] || '').toString();
101
+ const proto = forwardedProto || (req.raw && req.raw.socket && (req.raw.socket as any).encrypted ? 'https' : 'http');
102
+
103
+ // Decide whether to redirect: http -> https, www -> apex, or host mismatch
104
+ const isHttp = enforceHttps && proto !== 'https';
105
+ const isWww = redirectWww && normalizedHost.startsWith('www.');
106
+ const hostMismatch = mainDomain && normalizedHost !== mainDomain && normalizedHost !== `www.${mainDomain}`;
107
+
108
+ if (isHttp || isWww || hostMismatch) {
109
+ // Build target host (prefer configured mainDomain, else strip www.)
110
+ const targetHost = mainDomain ? mainDomain : normalizedHost.replace(/^www\./, '');
111
+ const targetProto = enforceHttps ? 'https' : proto;
112
+ const targetUrl = `${targetProto}://${targetHost}${req.url}`;
113
+
114
+ // Permanent redirect
115
+ reply.status(301).header('Cache-Control', 'public, max-age=31536000').redirect(targetUrl);
116
+ return;
117
+ }
118
+ } catch (e) {
119
+ // swallow errors and continue to avoid blocking requests
120
+ // eslint-disable-next-line no-console
121
+ console.warn('[harpy-core] redirect hook error', e);
122
+ }
123
+
124
+ done();
125
+ });
126
+ }
127
+
64
128
  // Set custom error handler BEFORE other plugins to catch 404s
65
129
  // This works with @fastify/static and catches all errors including 404s
66
130
  const NotFoundComponent = errorPages?.["404"] || Default404Page;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-401.js","sourceRoot":"","sources":["default-401.tsx"],"names":[],"mappings":";;AAOA,iCAmCC;;AAnCD,SAAwB,cAAc,CAAC,EACrC,OAAO,GAAG,cAAc,GACF;IACtB,OAAO,CACL,gCAAK,SAAS,EAAC,mGAAmG,YAChH,iCAAK,SAAS,EAAC,mEAAmE,aAChF,gCAAK,SAAS,EAAC,MAAM,YACnB,gCAAK,SAAS,EAAC,+HAA+H,YAC5I,iCAAM,SAAS,EAAC,UAAU,6BAAU,GAChC,GACF,EAEN,+BAAI,SAAS,EAAC,2GAA2G,oBAEpH,EAEL,+BAAI,SAAS,EAAC,uCAAuC,YAAE,OAAO,GAAM,EAEpE,8BAAG,SAAS,EAAC,4BAA4B,sEAErC,EAEJ,8BACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,kMAAkM,4BAG1M,EAEJ,+BAAG,SAAS,EAAC,6BAA6B,4BAC7B,iCAAM,SAAS,EAAC,+BAA+B,yBAAgB,IACxE,IACA,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-403.js","sourceRoot":"","sources":["default-403.tsx"],"names":[],"mappings":";;AAOA,iCAmCC;;AAnCD,SAAwB,cAAc,CAAC,EACrC,OAAO,GAAG,WAAW,GACF;IACnB,OAAO,CACL,gCAAK,SAAS,EAAC,gGAAgG,YAC7G,iCAAK,SAAS,EAAC,mEAAmE,aAChF,gCAAK,SAAS,EAAC,MAAM,YACnB,gCAAK,SAAS,EAAC,4HAA4H,YACzI,iCAAM,SAAS,EAAC,UAAU,uBAAS,GAC/B,GACF,EAEN,+BAAI,SAAS,EAAC,wGAAwG,oBAEjH,EAEL,+BAAI,SAAS,EAAC,uCAAuC,YAAE,OAAO,GAAM,EAEpE,8BAAG,SAAS,EAAC,4BAA4B,mEAErC,EAEJ,8BACE,IAAI,EAAC,GAAG,EACR,SAAS,EAAC,+LAA+L,+BAGvM,EAEJ,+BAAG,SAAS,EAAC,6BAA6B,4BAC7B,iCAAM,SAAS,EAAC,4BAA4B,yBAAgB,IACrE,IACA,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-404.js","sourceRoot":"","sources":["default-404.tsx"],"names":[],"mappings":";;AAQA,iCA6CC;;AA7CD,SAAwB,cAAc,CAAC,EACrC,IAAI,EACJ,OAAO,GAAG,gBAAgB,GACR;IAClB,OAAO,CACL,gCAAK,SAAS,EAAC,iGAAiG,YAC9G,iCAAK,SAAS,EAAC,mEAAmE,aAChF,gCAAK,SAAS,EAAC,MAAM,YACnB,gCAAK,SAAS,EAAC,6HAA6H,YAC1I,iCAAM,SAAS,EAAC,+BAA+B,kBAAS,GACpD,GACF,EAEN,+BAAI,SAAS,EAAC,yGAAyG,oBAElH,EAEL,+BAAI,SAAS,EAAC,uCAAuC,YAAE,OAAO,GAAM,EAEpE,8BAAG,SAAS,EAAC,4BAA4B,6EAErC,EAEH,IAAI,IAAI,CACP,gCAAK,SAAS,EAAC,wDAAwD,YACrE,+BAAG,SAAS,EAAC,iCAAiC,aAC5C,iCAAM,SAAS,EAAC,eAAe,gCAAuB,EAAC,GAAG,EAC1D,iCAAM,SAAS,EAAC,+BAA+B,YAAE,IAAI,GAAQ,IAC3D,GACA,CACP,EAED,8BACE,IAAI,EAAC,GAAG,EACR,SAAS,EAAC,gMAAgM,+BAGxM,EAEJ,+BAAG,SAAS,EAAC,6BAA6B,4BAC7B,iCAAM,SAAS,EAAC,+BAA+B,yBAAgB,IACxE,IACA,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-500.js","sourceRoot":"","sources":["default-500.tsx"],"names":[],"mappings":";;AAQA,iCAkDC;;AAlDD,SAAwB,cAAc,CAAC,EACrC,OAAO,GAAG,uBAAuB,EACjC,KAAK,GACgB;IACrB,OAAO,CACL,gCAAK,SAAS,EAAC,8FAA8F,YAC3G,iCAAK,SAAS,EAAC,mEAAmE,aAChF,gCAAK,SAAS,EAAC,MAAM,YACnB,gCAAK,SAAS,EAAC,0HAA0H,YACvI,iCAAM,SAAS,EAAC,+BAA+B,kBAAS,GACpD,GACF,EAEN,+BAAI,SAAS,EAAC,sGAAsG,oBAE/G,EAEL,+BAAI,SAAS,EAAC,uCAAuC,YAAE,OAAO,GAAM,EAEpE,8BAAG,SAAS,EAAC,4BAA4B,yEAErC,EAEH,KAAK,IAAI,CACR,gCAAK,SAAS,EAAC,iEAAiE,YAC9E,iCAAK,SAAS,EAAC,wBAAwB,aACrC,gCAAK,SAAS,EAAC,2CAA2C,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,OAAO,EAAC,WAAW,YAC9G,iCAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,WAAW,EAAE,CAAC,EAAE,CAAC,EAAC,mDAAmD,GAAG,GACvH,EACN,iCAAK,SAAS,EAAC,QAAQ,aACrB,+BAAI,SAAS,EAAC,yCAAyC,8BAAmB,EAC1E,gCAAK,SAAS,EAAC,gEAAgE,YAAE,KAAK,GAAO,IACzF,IACF,GACF,CACP,EAED,8BACE,IAAI,EAAC,GAAG,EACR,SAAS,EAAC,6LAA6L,+BAGrM,EAEJ,+BAAG,SAAS,EAAC,6BAA6B,4BAC7B,iCAAM,SAAS,EAAC,4BAA4B,yBAAgB,IACrE,IACA,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-layout.js","sourceRoot":"","sources":["error-layout.tsx"],"names":[],"mappings":";;AAWA,8BAkBC;;AAlBD,SAAwB,WAAW,CAAC,EAClC,QAAQ,EACR,KAAK,GAAG,OAAO,GACE;IACjB,OAAO,CACL,kCAAM,IAAI,EAAC,IAAI,aACb,6CACE,iCAAM,OAAO,EAAC,OAAO,GAAG,EACxB,iCAAM,IAAI,EAAC,UAAU,EAAC,OAAO,EAAC,qCAAqC,GAAG,EACtE,4CAAQ,KAAK,GAAS,EACtB,iCAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAC,oBAAoB,GAAG,EACnD,iCAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAC,oBAAoB,GAAG,IAC9C,EACP,2CACG,QAAQ,GACJ,IACF,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydration-manifest.js","sourceRoot":"","sources":["hydration-manifest.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,oDAqCC;AAKD,4CAGC;AAKD,oCAGC;AAKD,0DAEC;AAzED,uCAAyB;AACzB,2CAA6B;AAM7B,IAAI,cAAc,GAA6B,IAAI,CAAC;AAMpD,SAAgB,oBAAoB;IAClC,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IAGD,MAAM,aAAa,GAAG;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,yBAAyB,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,yBAAyB,CAAC;KAC3D,CAAC;IAEF,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CACV,gDAAgD,EAChD,aAAa,EACb,uCAAuC,CACxC,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACvD,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;QAC1D,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,KAAK,CAAC,CAAC;QACvE,cAAc,GAAG,EAAE,CAAC;QACpB,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAKD,SAAgB,gBAAgB,CAAC,aAAqB;IACpD,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;IACxC,OAAO,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC;AAKD,SAAgB,YAAY,CAAC,aAAqB;IAChD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC,CAAC,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAKD,SAAgB,uBAAuB;IACrC,cAAc,GAAG,IAAI,CAAC;AACxB,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydration.js","sourceRoot":"","sources":["hydration.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,gDAEC;AAKD,gEAKC;AAKD,0DAOC;AAKD,kDAMC;AAKD,sDAKC;AArED,6CAAgD;AAChD,+CAAiC;AAkBpB,QAAA,gBAAgB,GAAG,IAAI,+BAAiB,EAAoB,CAAC;AAK1E,SAAgB,kBAAkB,CAAC,aAAqB;IACtD,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AAClE,CAAC;AAKD,SAAgB,0BAA0B;IACxC,MAAM,OAAO,GAAqB;QAChC,gBAAgB,EAAE,IAAI,GAAG,EAAE;KAC5B,CAAC;IACF,OAAO,OAAO,CAAC;AACjB,CAAC;AAKD,SAAgB,uBAAuB,CACrC,QAAiC;IAEjC,MAAM,OAAO,GAAG,wBAAgB,CAAC,QAAQ,EAAE,CAAC;IAC5C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAKD,SAAgB,mBAAmB;IACjC,MAAM,OAAO,GAAG,wBAAgB,CAAC,QAAQ,EAAE,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;AACvD,CAAC;AAKD,SAAgB,qBAAqB;IACnC,MAAM,OAAO,GAAG,wBAAgB,CAAC,QAAQ,EAAE,CAAC;IAC5C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACnC,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-exception.filter.js","sourceRoot":"","sources":["jsx-exception.filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx.engine.js","sourceRoot":"","sources":["jsx.engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-reload.controller.js","sourceRoot":"","sources":["live-reload.controller.ts"],"names":[],"mappings":";;;AAMA,MAAa,oBAAoB;IACvB,OAAO,GAAmB,EAAE,CAAC;IAC7B,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEpC,UAAU,CAAC,KAAmB;QAE5B,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACvB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,UAAU,EAAE,YAAY;SACzB,CAAC,CAAC;QAGH,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAGzB,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;QAGtE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC1C,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAMD,aAAa;QACX,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAEM,YAAY;QACjB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC;QAElG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YAC9B,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;YAEf,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAhDD,oDAgDC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-assets.controller.js","sourceRoot":"","sources":["static-assets.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,uCAAyB;AACzB,2CAA6B;AAK7B,MAAa,sBAAsB;IACjC,gBAAgB,CAAC,KAAmB;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;QAEjE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF;AAXD,wDAWC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx.decorator.js","sourceRoot":"","sources":["jsx.decorator.ts"],"names":[],"mappings":";;AAiCA,8BAgBC;AAjDD,wDAA2D;AAiC3D,SAAgB,SAAS,CACvB,QAAwC,EACxC,UAAyB,EAAE;IAE3B,OAAO,CACL,MAAc,EACd,GAAoB,EACpB,UAAwC,EACxC,EAAE;QACF,OAAO,CAAC,cAAc,CACpB,2BAAe,EACf,CAAC,QAAQ,EAAE,OAAO,CAAC,EACnB,UAAU,CAAC,KAAK,CACjB,CAAC;QACF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx.types.js","sourceRoot":"","sources":["jsx.types.ts"],"names":[],"mappings":""}