@useavalon/avalon 0.1.4 → 0.1.6
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/package.json +31 -58
- package/src/vite-plugin/plugin.ts +22 -4
- package/src/build/README.md +0 -310
- package/src/client/tests/css-hmr-handler.test.ts +0 -360
- package/src/client/tests/framework-adapter.test.ts +0 -519
- package/src/client/tests/hmr-coordinator.test.ts +0 -176
- package/src/client/tests/hydration-option-parsing.test.ts +0 -107
- package/src/client/tests/lit-adapter.test.ts +0 -427
- package/src/client/tests/preact-adapter.test.ts +0 -353
- package/src/client/tests/qwik-adapter.test.ts +0 -343
- package/src/client/tests/react-adapter.test.ts +0 -317
- package/src/client/tests/solid-adapter.test.ts +0 -396
- package/src/client/tests/svelte-adapter.test.ts +0 -387
- package/src/client/tests/vue-adapter.test.ts +0 -407
- package/src/components/tests/component-analyzer.test.ts +0 -96
- package/src/components/tests/component-detection.test.ts +0 -347
- package/src/components/tests/persistent-islands.test.ts +0 -398
- package/src/core/components/tests/enhanced-framework-detector.test.ts +0 -577
- package/src/core/components/tests/framework-registry.test.ts +0 -465
- package/src/core/integrations/README.md +0 -282
- package/src/core/layout/tests/enhanced-layout-resolver.test.ts +0 -477
- package/src/core/layout/tests/layout-cache-optimization.test.ts +0 -149
- package/src/core/layout/tests/layout-composer.test.ts +0 -486
- package/src/core/layout/tests/layout-data-loader.test.ts +0 -443
- package/src/core/layout/tests/layout-discovery.test.ts +0 -253
- package/src/core/layout/tests/layout-matcher.test.ts +0 -480
- package/src/core/modules/tests/framework-module-resolver.test.ts +0 -263
- package/src/core/modules/tests/module-resolution-integration.test.ts +0 -117
- package/src/islands/discovery/tests/island-discovery.test.ts +0 -881
- package/src/middleware/__tests__/discovery.test.ts +0 -107
- package/src/types/tests/layout-types.test.ts +0 -197
- package/src/vite-plugin/tests/image-optimization.test.ts +0 -54
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises';
|
|
4
|
-
import { tmpdir } from 'node:os';
|
|
5
|
-
import { discoverScopedMiddleware, getMatchingMiddleware } from '../discovery.ts';
|
|
6
|
-
|
|
7
|
-
describe('discoverScopedMiddleware', () => {
|
|
8
|
-
let tempDir: string;
|
|
9
|
-
|
|
10
|
-
beforeEach(async () => {
|
|
11
|
-
tempDir = await mkdtemp(join(tmpdir(), 'middleware-test-'));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
afterEach(async () => {
|
|
15
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('discovers _middleware.ts files in pages subdirectories', async () => {
|
|
19
|
-
// Create pages directory structure with middleware files
|
|
20
|
-
await mkdir(join(tempDir, 'pages', 'admin'), { recursive: true });
|
|
21
|
-
await mkdir(join(tempDir, 'pages', 'blog'), { recursive: true });
|
|
22
|
-
await writeFile(join(tempDir, 'pages', 'admin', '_middleware.ts'), 'export default () => {};');
|
|
23
|
-
await writeFile(join(tempDir, 'pages', 'blog', '_middleware.ts'), 'export default () => {};');
|
|
24
|
-
|
|
25
|
-
const routes = await discoverScopedMiddleware({ baseDir: tempDir });
|
|
26
|
-
|
|
27
|
-
expect(routes).toHaveLength(2);
|
|
28
|
-
expect(routes.every(r => r.type === 'pages')).toBe(true);
|
|
29
|
-
expect(routes.map(r => r.filePath)).toEqual(
|
|
30
|
-
expect.arrayContaining([
|
|
31
|
-
join(tempDir, 'pages', 'admin', '_middleware.ts'),
|
|
32
|
-
join(tempDir, 'pages', 'blog', '_middleware.ts'),
|
|
33
|
-
])
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('discovers nested _middleware.ts files with correct priority ordering', async () => {
|
|
38
|
-
await mkdir(join(tempDir, 'pages', 'admin', 'users'), { recursive: true });
|
|
39
|
-
await writeFile(join(tempDir, 'pages', 'admin', '_middleware.ts'), 'export default () => {};');
|
|
40
|
-
await writeFile(join(tempDir, 'pages', 'admin', 'users', '_middleware.ts'), 'export default () => {};');
|
|
41
|
-
|
|
42
|
-
const routes = await discoverScopedMiddleware({ baseDir: tempDir });
|
|
43
|
-
|
|
44
|
-
expect(routes).toHaveLength(2);
|
|
45
|
-
// Parent middleware (depth 1) should come before child (depth 2)
|
|
46
|
-
expect(routes[0].priority).toBeLessThan(routes[1].priority);
|
|
47
|
-
expect(routes[0].filePath).toContain(join('admin', '_middleware.ts'));
|
|
48
|
-
expect(routes[1].filePath).toContain(join('admin', 'users', '_middleware.ts'));
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('does NOT scan api directory for middleware', async () => {
|
|
52
|
-
await mkdir(join(tempDir, 'pages', 'admin'), { recursive: true });
|
|
53
|
-
await mkdir(join(tempDir, 'api', 'admin'), { recursive: true });
|
|
54
|
-
await writeFile(join(tempDir, 'pages', 'admin', '_middleware.ts'), 'export default () => {};');
|
|
55
|
-
await writeFile(join(tempDir, 'api', 'admin', '_middleware.ts'), 'export default () => {};');
|
|
56
|
-
|
|
57
|
-
const routes = await discoverScopedMiddleware({ baseDir: tempDir });
|
|
58
|
-
|
|
59
|
-
expect(routes).toHaveLength(1);
|
|
60
|
-
expect(routes[0].type).toBe('pages');
|
|
61
|
-
expect(routes[0].filePath).toContain(join('pages', 'admin', '_middleware.ts'));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('returns empty array when no middleware files exist', async () => {
|
|
65
|
-
await mkdir(join(tempDir, 'pages'), { recursive: true });
|
|
66
|
-
|
|
67
|
-
const routes = await discoverScopedMiddleware({ baseDir: tempDir });
|
|
68
|
-
|
|
69
|
-
expect(routes).toHaveLength(0);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('returns empty array when pages directory does not exist', async () => {
|
|
73
|
-
const routes = await discoverScopedMiddleware({ baseDir: tempDir });
|
|
74
|
-
|
|
75
|
-
expect(routes).toHaveLength(0);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe('getMatchingMiddleware', () => {
|
|
80
|
-
it('matches page middleware for page routes', () => {
|
|
81
|
-
const routes = [
|
|
82
|
-
{
|
|
83
|
-
pattern: new URLPattern({ pathname: '/admin{/*}?' }),
|
|
84
|
-
filePath: '/src/pages/admin/_middleware.ts',
|
|
85
|
-
priority: 51,
|
|
86
|
-
type: 'pages' as const,
|
|
87
|
-
},
|
|
88
|
-
];
|
|
89
|
-
|
|
90
|
-
const matches = getMatchingMiddleware(routes, new URL('http://localhost/admin/dashboard'));
|
|
91
|
-
expect(matches).toHaveLength(1);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('does not match page middleware for API routes', () => {
|
|
95
|
-
const routes = [
|
|
96
|
-
{
|
|
97
|
-
pattern: new URLPattern({ pathname: '/*' }),
|
|
98
|
-
filePath: '/src/pages/_middleware.ts',
|
|
99
|
-
priority: 50,
|
|
100
|
-
type: 'pages' as const,
|
|
101
|
-
},
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
const matches = getMatchingMiddleware(routes, new URL('http://localhost/api/users'));
|
|
105
|
-
expect(matches).toHaveLength(0);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
LayoutContextSchema,
|
|
4
|
-
LayoutDataSchema,
|
|
5
|
-
LayoutRouteSchema,
|
|
6
|
-
LayoutHandlerSchema,
|
|
7
|
-
LayoutPropsSchema,
|
|
8
|
-
LayoutDiscoveryOptionsSchema,
|
|
9
|
-
LayoutConfigSchema,
|
|
10
|
-
ResolvedLayoutSchema,
|
|
11
|
-
} from '../../schemas/layout.ts';
|
|
12
|
-
import { validators, safeValidators } from '../../schemas/index.ts';
|
|
13
|
-
import type {
|
|
14
|
-
LayoutContext,
|
|
15
|
-
LayoutData,
|
|
16
|
-
LayoutRoute,
|
|
17
|
-
LayoutHandler,
|
|
18
|
-
LayoutProps,
|
|
19
|
-
LayoutDiscoveryOptions,
|
|
20
|
-
LayoutConfig,
|
|
21
|
-
ResolvedLayout,
|
|
22
|
-
} from '../layout.ts';
|
|
23
|
-
|
|
24
|
-
describe('Layout System Types and Schemas', () => {
|
|
25
|
-
it('LayoutContext - should validate valid layout context', () => {
|
|
26
|
-
const mockRequest = new Request('https://example.com/test');
|
|
27
|
-
const mockParams = { id: '123' };
|
|
28
|
-
const mockQuery = new URLSearchParams('?page=1');
|
|
29
|
-
const mockState = new Map();
|
|
30
|
-
|
|
31
|
-
const validContext: LayoutContext = {
|
|
32
|
-
request: mockRequest,
|
|
33
|
-
params: mockParams,
|
|
34
|
-
query: mockQuery,
|
|
35
|
-
state: mockState,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const result = safeValidators.layoutContext(validContext);
|
|
39
|
-
expect(result.success).toEqual(true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('LayoutContext - should reject invalid layout context', () => {
|
|
43
|
-
const invalidContext = {
|
|
44
|
-
request: 'not-a-request',
|
|
45
|
-
params: 'not-an-object',
|
|
46
|
-
query: 'not-urlsearchparams',
|
|
47
|
-
state: 'not-a-map',
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const result = safeValidators.layoutContext(invalidContext);
|
|
51
|
-
expect(result.success).toEqual(false);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('LayoutData - should validate layout data as record', () => {
|
|
55
|
-
const validData: LayoutData = {
|
|
56
|
-
user: { name: 'John', id: 123 },
|
|
57
|
-
settings: { theme: 'dark' },
|
|
58
|
-
items: [1, 2, 3],
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const result = safeValidators.layoutData(validData);
|
|
62
|
-
expect(result.success).toEqual(true);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('LayoutData - should accept empty layout data', () => {
|
|
66
|
-
const emptyData: LayoutData = {};
|
|
67
|
-
|
|
68
|
-
const result = safeValidators.layoutData(emptyData);
|
|
69
|
-
expect(result.success).toEqual(true);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('LayoutHandler - should validate valid layout handler', () => {
|
|
73
|
-
const validHandler = {
|
|
74
|
-
component: () => null,
|
|
75
|
-
path: '/src/pages/blog/_layout.tsx',
|
|
76
|
-
priority: 10,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const result = safeValidators.layoutHandler(validHandler);
|
|
80
|
-
expect(result.success).toEqual(true);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('LayoutDiscoveryOptions - should validate with defaults', () => {
|
|
84
|
-
const options = {
|
|
85
|
-
baseDirectory: '/src/pages',
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const result = safeValidators.layoutDiscoveryOptions(options);
|
|
89
|
-
expect(result.success).toEqual(true);
|
|
90
|
-
if (result.success) {
|
|
91
|
-
expect(result.data.filePattern).toEqual('_layout.tsx');
|
|
92
|
-
expect(result.data.excludeDirectories).toEqual([]);
|
|
93
|
-
expect(result.data.enableWatching).toEqual(false);
|
|
94
|
-
expect(result.data.developmentMode).toEqual(false);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('LayoutDiscoveryOptions - should validate with custom options', () => {
|
|
99
|
-
const options: LayoutDiscoveryOptions = {
|
|
100
|
-
baseDirectory: '/src/pages',
|
|
101
|
-
filePattern: 'layout.tsx',
|
|
102
|
-
excludeDirectories: ['node_modules', '.git'],
|
|
103
|
-
enableWatching: true,
|
|
104
|
-
developmentMode: true,
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const result = safeValidators.layoutDiscoveryOptions(options);
|
|
108
|
-
expect(result.success).toEqual(true);
|
|
109
|
-
if (result.success) {
|
|
110
|
-
expect(result.data.filePattern).toEqual('layout.tsx');
|
|
111
|
-
expect(result.data.excludeDirectories).toEqual(['node_modules', '.git']);
|
|
112
|
-
expect(result.data.enableWatching).toEqual(true);
|
|
113
|
-
expect(result.data.developmentMode).toEqual(true);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('LayoutConfig - should validate layout config with all options', () => {
|
|
118
|
-
const config: LayoutConfig = {
|
|
119
|
-
skipLayouts: ['root', 'admin'],
|
|
120
|
-
replaceLayout: true,
|
|
121
|
-
onlyLayouts: ['custom'],
|
|
122
|
-
customLayout: '/custom/layout.tsx',
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const result = safeValidators.layoutConfig(config);
|
|
126
|
-
expect(result.success).toEqual(true);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('LayoutConfig - should validate empty layout config', () => {
|
|
130
|
-
const config: LayoutConfig = {};
|
|
131
|
-
|
|
132
|
-
const result = safeValidators.layoutConfig(config);
|
|
133
|
-
expect(result.success).toEqual(true);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('ResolvedLayout - should validate complete resolved layout', () => {
|
|
137
|
-
const resolvedLayout: ResolvedLayout = {
|
|
138
|
-
handlers: [],
|
|
139
|
-
dataLoaders: [],
|
|
140
|
-
errorBoundaries: [],
|
|
141
|
-
streamingComponents: [],
|
|
142
|
-
metadata: {
|
|
143
|
-
totalLayouts: 2,
|
|
144
|
-
resolutionTime: 15.5,
|
|
145
|
-
cacheHit: false,
|
|
146
|
-
},
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const result = safeValidators.resolvedLayout(resolvedLayout);
|
|
150
|
-
expect(result.success).toEqual(true);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('ResolvedLayout - should require all metadata fields', () => {
|
|
154
|
-
const incompleteLayout = {
|
|
155
|
-
handlers: [],
|
|
156
|
-
dataLoaders: [],
|
|
157
|
-
errorBoundaries: [],
|
|
158
|
-
streamingComponents: [],
|
|
159
|
-
metadata: {
|
|
160
|
-
totalLayouts: 2,
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const result = safeValidators.resolvedLayout(incompleteLayout);
|
|
165
|
-
expect(result.success).toEqual(false);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('Type compatibility - should ensure TypeScript types match Zod schemas', () => {
|
|
169
|
-
const mockRequest = new Request('https://example.com');
|
|
170
|
-
const layoutContext: LayoutContext = {
|
|
171
|
-
request: mockRequest,
|
|
172
|
-
params: { id: '123' },
|
|
173
|
-
query: new URLSearchParams(),
|
|
174
|
-
state: new Map(),
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const validatedContext = validators.layoutContext(layoutContext);
|
|
178
|
-
expect(validatedContext).toBeDefined();
|
|
179
|
-
expect(validatedContext.request).toEqual(mockRequest);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('Error handling - should provide meaningful error messages', () => {
|
|
183
|
-
const invalidData = {
|
|
184
|
-
request: null,
|
|
185
|
-
params: null,
|
|
186
|
-
query: null,
|
|
187
|
-
state: null,
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const result = safeValidators.layoutContext(invalidData);
|
|
191
|
-
expect(result.success).toEqual(false);
|
|
192
|
-
if (!result.success) {
|
|
193
|
-
expect(result.error.message).toContain('Invalid layout context');
|
|
194
|
-
expect(result.error.getFormattedErrors().length > 0).toEqual(true);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
});
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { createImagePlugin } from "../image-optimization.ts";
|
|
3
|
-
import type { ResolvedImageConfig } from "../types.ts";
|
|
4
|
-
|
|
5
|
-
describe("createImagePlugin", () => {
|
|
6
|
-
const defaultConfig: ResolvedImageConfig = {
|
|
7
|
-
enabled: true,
|
|
8
|
-
defaultFormat: "webp",
|
|
9
|
-
quality: 80,
|
|
10
|
-
widths: [200, 400, 600, 800, 1200],
|
|
11
|
-
removeMetadata: true,
|
|
12
|
-
include: /^[^?]+\.(heif|avif|jpeg|jpg|png|tiff|webp|gif)(\?.*)?$/,
|
|
13
|
-
exclude: "public/**/*",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
vi.clearAllMocks();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("returns empty array when disabled", async () => {
|
|
21
|
-
const plugins = await createImagePlugin({ ...defaultConfig, enabled: false }, false);
|
|
22
|
-
expect(plugins).toEqual([]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("returns imagetools plugin when enabled", async () => {
|
|
26
|
-
const plugins = await createImagePlugin(defaultConfig, false);
|
|
27
|
-
expect(plugins.length).toBe(1);
|
|
28
|
-
expect(plugins[0].name).toBe("imagetools");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("logs info when verbose is true", async () => {
|
|
32
|
-
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
33
|
-
|
|
34
|
-
await createImagePlugin(defaultConfig, true);
|
|
35
|
-
|
|
36
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Image optimization enabled"));
|
|
37
|
-
consoleSpy.mockRestore();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("respects custom format setting", async () => {
|
|
41
|
-
const plugins = await createImagePlugin({ ...defaultConfig, defaultFormat: "avif" }, true);
|
|
42
|
-
expect(plugins.length).toBe(1);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("respects custom quality setting", async () => {
|
|
46
|
-
const plugins = await createImagePlugin({ ...defaultConfig, quality: 90 }, false);
|
|
47
|
-
expect(plugins.length).toBe(1);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("respects custom widths setting", async () => {
|
|
51
|
-
const plugins = await createImagePlugin({ ...defaultConfig, widths: [320, 640, 1280] }, false);
|
|
52
|
-
expect(plugins.length).toBe(1);
|
|
53
|
-
});
|
|
54
|
-
});
|