@ecopages/core 0.2.0-alpha.25 → 0.2.0-alpha.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -7
- package/package.json +4 -47
- package/src/adapters/bun/create-app.ts +54 -2
- package/src/adapters/bun/hmr-manager.test.ts +0 -2
- package/src/adapters/bun/hmr-manager.ts +1 -24
- package/src/adapters/bun/server-adapter.ts +30 -4
- package/src/adapters/node/node-hmr-manager.test.ts +0 -2
- package/src/adapters/node/node-hmr-manager.ts +2 -25
- package/src/adapters/shared/explicit-static-render-preparation.ts +58 -0
- package/src/adapters/shared/explicit-static-route-matcher.test.ts +6 -6
- package/src/adapters/shared/explicit-static-route-matcher.ts +22 -31
- package/src/adapters/shared/file-route-middleware-pipeline.test.ts +5 -10
- package/src/adapters/shared/file-route-middleware-pipeline.ts +8 -17
- package/src/adapters/shared/fs-server-response-factory.test.ts +32 -43
- package/src/adapters/shared/fs-server-response-factory.ts +15 -37
- package/src/adapters/shared/fs-server-response-matcher.test.ts +65 -39
- package/src/adapters/shared/fs-server-response-matcher.ts +94 -43
- package/src/adapters/shared/hmr-manager.contract.test.ts +0 -4
- package/src/adapters/shared/render-context.ts +3 -3
- package/src/adapters/shared/server-adapter.test.ts +53 -0
- package/src/adapters/shared/server-adapter.ts +228 -159
- package/src/adapters/shared/server-route-handler.test.ts +6 -5
- package/src/adapters/shared/server-route-handler.ts +4 -4
- package/src/adapters/shared/server-static-builder.test.ts +4 -4
- package/src/adapters/shared/server-static-builder.ts +4 -4
- package/src/config/README.md +1 -1
- package/src/config/config-builder.test.ts +0 -1
- package/src/config/config-builder.ts +2 -7
- package/src/dev/host-runtime.ts +34 -0
- package/src/eco/eco.browser.test.ts +2 -2
- package/src/eco/eco.browser.ts +2 -2
- package/src/eco/eco.test.ts +6 -6
- package/src/eco/eco.ts +12 -12
- package/src/eco/eco.types.ts +3 -3
- package/src/errors/index.ts +1 -0
- package/src/hmr/client/hmr-runtime.ts +4 -2
- package/src/hmr/strategies/js-hmr-strategy.test.ts +0 -1
- package/src/hmr/strategies/js-hmr-strategy.ts +0 -6
- package/src/integrations/ghtml/ghtml-renderer.test.ts +7 -7
- package/src/integrations/ghtml/ghtml-renderer.ts +1 -11
- package/src/plugins/eco-component-meta-plugin.ts +0 -1
- package/src/plugins/integration-plugin.test.ts +9 -14
- package/src/plugins/integration-plugin.ts +34 -22
- package/src/plugins/processor.ts +17 -0
- package/src/route-renderer/GRAPH.md +81 -289
- package/src/route-renderer/README.md +67 -105
- package/src/route-renderer/orchestration/component-render-context.ts +45 -38
- package/src/route-renderer/orchestration/declared-ownership-graph.ts +62 -0
- package/src/route-renderer/orchestration/foreign-subtree-execution.service.ts +383 -0
- package/src/route-renderer/orchestration/integration-renderer.test.ts +118 -121
- package/src/route-renderer/orchestration/integration-renderer.ts +362 -403
- package/src/route-renderer/orchestration/ownership-planning.service.ts +97 -0
- package/src/route-renderer/orchestration/ownership-validation.service.ts +76 -0
- package/src/route-renderer/orchestration/processed-asset-dedupe.ts +1 -1
- package/src/route-renderer/orchestration/{queued-boundary-runtime.service.test.ts → queued-foreign-subtree-resolution.service.test.ts} +76 -71
- package/src/route-renderer/orchestration/{queued-boundary-runtime.service.ts → queued-foreign-subtree-resolution.service.ts} +68 -63
- package/src/route-renderer/orchestration/render-output.utils.ts +21 -13
- package/src/route-renderer/orchestration/{render-preparation.service.test.ts → route-render-orchestrator.prepare-render-options.test.ts} +160 -85
- package/src/route-renderer/orchestration/route-render-orchestrator.test.ts +265 -0
- package/src/route-renderer/orchestration/{render-preparation.service.ts → route-render-orchestrator.ts} +244 -160
- package/src/route-renderer/page-loading/component-dependency-collection.ts +9 -3
- package/src/route-renderer/page-loading/declared-asset-collection.ts +2 -5
- package/src/route-renderer/page-loading/dependency-resolver.test.ts +107 -11
- package/src/route-renderer/page-loading/dependency-resolver.ts +6 -12
- package/src/route-renderer/page-loading/ecopages-virtual-imports.ts +1 -1
- package/src/route-renderer/page-loading/lazy-entry-collection.ts +1 -1
- package/src/route-renderer/page-loading/lazy-trigger-planning.ts +1 -1
- package/src/route-renderer/page-loading/module-declaration-aggregation.ts +1 -1
- package/src/route-renderer/page-loading/module-declaration-scripts.ts +1 -1
- package/src/route-renderer/page-loading/page-dependency-bundling.ts +105 -66
- package/src/route-renderer/route-renderer.ts +28 -31
- package/src/router/README.md +16 -19
- package/src/router/server/route-registry.test.ts +176 -0
- package/src/router/server/route-registry.ts +382 -0
- package/src/services/README.md +1 -2
- package/src/services/assets/asset-processing-service/asset-dependency-keys.ts +1 -1
- package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +1 -4
- package/src/services/assets/asset-processing-service/asset-processing.service.ts +1 -2
- package/src/services/assets/asset-processing-service/assets.types.ts +3 -0
- package/src/services/assets/asset-processing-service/grouped-content-bundles.ts +1 -1
- package/src/services/assets/asset-processing-service/index.ts +1 -0
- package/src/{route-renderer/orchestration/page-packaging.service.test.ts → services/assets/asset-processing-service/page-package.test.ts} +38 -14
- package/src/services/assets/asset-processing-service/page-package.ts +93 -0
- package/src/services/assets/asset-processing-service/processors/base/base-script-processor.ts +4 -5
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.test.ts +13 -10
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.ts +3 -0
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.ts +6 -0
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.ts +2 -0
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +1 -0
- package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +2 -0
- package/src/services/assets/asset-processing-service/ungrouped-dependency-processing.ts +1 -1
- package/src/services/html/html-transformer.service.test.ts +1 -4
- package/src/services/module-loading/app-server-module-transpiler.service.ts +1 -3
- package/src/services/module-loading/node-bootstrap-plugin.ts +17 -3
- package/src/services/module-loading/page-module-import.service.ts +0 -1
- package/src/services/module-loading/source-module-support.ts +1 -1
- package/src/static-site-generator/static-site-generator.test.ts +124 -32
- package/src/static-site-generator/static-site-generator.ts +168 -185
- package/src/types/internal-types.ts +13 -12
- package/src/types/public-types.ts +55 -39
- package/src/watchers/project-watcher.test-helpers.ts +4 -3
- package/src/route-renderer/orchestration/boundary-planning.service.ts +0 -146
- package/src/route-renderer/orchestration/page-packaging.service.ts +0 -85
- package/src/route-renderer/orchestration/render-execution.service.test.ts +0 -196
- package/src/route-renderer/orchestration/render-execution.service.ts +0 -182
- package/src/route-renderer/orchestration/route-shell-composer.service.ts +0 -162
- package/src/router/server/fs-router-scanner.test.ts +0 -83
- package/src/router/server/fs-router-scanner.ts +0 -224
- package/src/router/server/fs-router.test.ts +0 -214
- package/src/router/server/fs-router.ts +0 -122
- package/src/services/runtime-state/runtime-specifier-registry.service.ts +0 -96
|
@@ -2,8 +2,6 @@ import { describe, expect, test, beforeEach, afterEach, vi } from 'vitest';
|
|
|
2
2
|
import { fileSystem } from '@ecopages/file-system';
|
|
3
3
|
import { StaticSiteGenerator } from './static-site-generator';
|
|
4
4
|
import type { EcoPagesAppConfig } from '../types/internal-types';
|
|
5
|
-
import type { FSRouter } from '../router/server/fs-router';
|
|
6
|
-
import type { RouteRendererFactory } from '../route-renderer/route-renderer';
|
|
7
5
|
import { appLogger } from '../global/app-logger.ts';
|
|
8
6
|
import { DEFAULT_ECOPAGES_WORK_DIR } from '../config/constants.ts';
|
|
9
7
|
|
|
@@ -30,6 +28,17 @@ const createMockConfig = (overrides: Partial<EcoPagesAppConfig> = {}): EcoPagesA
|
|
|
30
28
|
...overrides,
|
|
31
29
|
}) as EcoPagesAppConfig;
|
|
32
30
|
|
|
31
|
+
const testInjectedMeta = {
|
|
32
|
+
id: 'test-page',
|
|
33
|
+
file: '/src/pages/test.tsx',
|
|
34
|
+
integration: 'test',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type StaticGenerationRouteSource = Parameters<StaticSiteGenerator['generateStaticPages']>[0];
|
|
38
|
+
type StaticPageRouteRendererFactory = NonNullable<Parameters<StaticSiteGenerator['generateStaticPages']>[2]>;
|
|
39
|
+
type StaticGenerationRendererFactory = NonNullable<Parameters<StaticSiteGenerator['run']>[0]['routeRendererFactory']>;
|
|
40
|
+
type StaticGenerationRunnerInput = Parameters<StaticSiteGenerator['run']>[0];
|
|
41
|
+
|
|
33
42
|
describe('StaticSiteGenerator', () => {
|
|
34
43
|
let ensureDirMock: any;
|
|
35
44
|
let writeMock: any;
|
|
@@ -144,11 +153,21 @@ describe('StaticSiteGenerator', () => {
|
|
|
144
153
|
describe('generateStaticPages', () => {
|
|
145
154
|
const createMockRouter = (routes: Record<string, { filePath: string; pathname: string }>) =>
|
|
146
155
|
({
|
|
147
|
-
|
|
148
|
-
Object.
|
|
156
|
+
listStaticGenerationRoutes: vi.fn(async () =>
|
|
157
|
+
Object.values(routes)
|
|
158
|
+
.filter((value) => !value.pathname.includes('['))
|
|
159
|
+
.map((value) => ({
|
|
160
|
+
requestUrl: `http://localhost:3000${value.pathname}`,
|
|
161
|
+
pathname: value.pathname,
|
|
162
|
+
templateRoute: {
|
|
163
|
+
...value,
|
|
164
|
+
kind: 'exact' as const,
|
|
165
|
+
paramNames: [],
|
|
166
|
+
},
|
|
167
|
+
params: {},
|
|
168
|
+
})),
|
|
149
169
|
),
|
|
150
|
-
|
|
151
|
-
}) as unknown as FSRouter;
|
|
170
|
+
}) satisfies StaticGenerationRouteSource;
|
|
152
171
|
|
|
153
172
|
const createStaticPageModule = () => ({
|
|
154
173
|
default: Object.assign(() => null, { cache: 'static' }),
|
|
@@ -162,11 +181,11 @@ describe('StaticSiteGenerator', () => {
|
|
|
162
181
|
});
|
|
163
182
|
|
|
164
183
|
const RendererFactory = {
|
|
165
|
-
|
|
184
|
+
getPageRenderer: vi.fn(() => ({
|
|
166
185
|
loadPageModule: vi.fn(async () => createStaticPageModule()),
|
|
167
|
-
|
|
186
|
+
execute: vi.fn(async () => ({ body: '<html>Static</html>' })),
|
|
168
187
|
})),
|
|
169
|
-
}
|
|
188
|
+
} satisfies StaticPageRouteRendererFactory;
|
|
170
189
|
|
|
171
190
|
await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
|
|
172
191
|
|
|
@@ -180,11 +199,11 @@ describe('StaticSiteGenerator', () => {
|
|
|
180
199
|
});
|
|
181
200
|
|
|
182
201
|
const RendererFactory = {
|
|
183
|
-
|
|
202
|
+
getPageRenderer: vi.fn(() => ({
|
|
184
203
|
loadPageModule: vi.fn(async () => createStaticPageModule()),
|
|
185
|
-
|
|
204
|
+
execute: vi.fn(async () => ({ body: '<html>Blog Post</html>' })),
|
|
186
205
|
})),
|
|
187
|
-
}
|
|
206
|
+
} satisfies StaticPageRouteRendererFactory;
|
|
188
207
|
|
|
189
208
|
await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
|
|
190
209
|
|
|
@@ -207,11 +226,11 @@ describe('StaticSiteGenerator', () => {
|
|
|
207
226
|
});
|
|
208
227
|
|
|
209
228
|
const RendererFactory = {
|
|
210
|
-
|
|
229
|
+
getPageRenderer: vi.fn(() => ({
|
|
211
230
|
loadPageModule: vi.fn(async () => createStaticPageModule()),
|
|
212
|
-
|
|
231
|
+
execute: vi.fn(async () => ({ body: '<html>Home</html>' })),
|
|
213
232
|
})),
|
|
214
|
-
}
|
|
233
|
+
} satisfies StaticPageRouteRendererFactory;
|
|
215
234
|
|
|
216
235
|
await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
|
|
217
236
|
|
|
@@ -226,11 +245,11 @@ describe('StaticSiteGenerator', () => {
|
|
|
226
245
|
|
|
227
246
|
const bufferContent = Buffer.from('<html>Buffer Content</html>');
|
|
228
247
|
const RendererFactory = {
|
|
229
|
-
|
|
248
|
+
getPageRenderer: vi.fn(() => ({
|
|
230
249
|
loadPageModule: vi.fn(async () => createStaticPageModule()),
|
|
231
|
-
|
|
250
|
+
execute: vi.fn(async () => ({ body: bufferContent })),
|
|
232
251
|
})),
|
|
233
|
-
}
|
|
252
|
+
} satisfies StaticPageRouteRendererFactory;
|
|
234
253
|
|
|
235
254
|
await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
|
|
236
255
|
|
|
@@ -243,24 +262,24 @@ describe('StaticSiteGenerator', () => {
|
|
|
243
262
|
'/dashboard': { filePath: '/src/pages/dashboard.tsx', pathname: '/dashboard' },
|
|
244
263
|
});
|
|
245
264
|
|
|
246
|
-
const
|
|
265
|
+
const execute = vi.fn(async () => ({ body: '<html>Dashboard</html>' }));
|
|
247
266
|
const loadPageModule = vi.fn(async () => ({
|
|
248
267
|
default: Object.assign(() => null, { cache: 'dynamic' }),
|
|
249
268
|
}));
|
|
250
269
|
const RendererFactory = {
|
|
251
|
-
|
|
252
|
-
|
|
270
|
+
getPageRenderer: vi.fn(() => ({
|
|
271
|
+
execute,
|
|
253
272
|
loadPageModule,
|
|
254
273
|
})),
|
|
255
|
-
}
|
|
274
|
+
} satisfies StaticPageRouteRendererFactory;
|
|
256
275
|
|
|
257
276
|
await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
|
|
258
277
|
|
|
259
|
-
expect(RendererFactory.
|
|
278
|
+
expect(RendererFactory.getPageRenderer).toHaveBeenCalledWith('/src/pages/dashboard.tsx');
|
|
260
279
|
expect(loadPageModule).toHaveBeenCalledWith('/src/pages/dashboard.tsx', {
|
|
261
280
|
cacheScope: 'static-page-probe',
|
|
262
281
|
});
|
|
263
|
-
expect(
|
|
282
|
+
expect(execute).not.toHaveBeenCalled();
|
|
264
283
|
expect(writeMock).not.toHaveBeenCalled();
|
|
265
284
|
expect(appLogger.warn).toHaveBeenCalledWith(
|
|
266
285
|
"Pages with cache: 'dynamic' are not supported in static generation or preview, so they will be skipped\n",
|
|
@@ -273,9 +292,8 @@ describe('StaticSiteGenerator', () => {
|
|
|
273
292
|
test('should call generateRobotsTxt and generateStaticPages', async () => {
|
|
274
293
|
const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
|
|
275
294
|
const Router = {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
} as unknown as FSRouter;
|
|
295
|
+
listStaticGenerationRoutes: vi.fn(async () => []),
|
|
296
|
+
} satisfies StaticGenerationRouteSource;
|
|
279
297
|
|
|
280
298
|
await ssg.run({
|
|
281
299
|
router: Router,
|
|
@@ -292,13 +310,13 @@ describe('StaticSiteGenerator', () => {
|
|
|
292
310
|
|
|
293
311
|
await ssg.run({
|
|
294
312
|
router: {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
} as unknown as FSRouter,
|
|
313
|
+
listStaticGenerationRoutes: vi.fn(async () => []),
|
|
314
|
+
} satisfies StaticGenerationRunnerInput['router'],
|
|
298
315
|
baseUrl: 'http://localhost:3000',
|
|
299
316
|
routeRendererFactory: {
|
|
300
|
-
|
|
301
|
-
|
|
317
|
+
getPageRenderer: vi.fn(),
|
|
318
|
+
getExplicitViewRenderer: vi.fn(),
|
|
319
|
+
} satisfies StaticGenerationRendererFactory,
|
|
302
320
|
staticRoutes: [
|
|
303
321
|
{
|
|
304
322
|
path: '/dashboard',
|
|
@@ -312,5 +330,79 @@ describe('StaticSiteGenerator', () => {
|
|
|
312
330
|
'➤ /dashboard',
|
|
313
331
|
);
|
|
314
332
|
});
|
|
333
|
+
|
|
334
|
+
test('should render dynamic explicit static routes from staticPaths', async () => {
|
|
335
|
+
const ssg = new StaticSiteGenerator({
|
|
336
|
+
appConfig: createMockConfig({ baseUrl: 'http://localhost:3000' } as any),
|
|
337
|
+
});
|
|
338
|
+
const renderToResponse = vi.fn(async () => new Response('<html>Post</html>'));
|
|
339
|
+
const staticProps = vi.fn(async ({ pathname }) => ({
|
|
340
|
+
props: pathname.params,
|
|
341
|
+
}));
|
|
342
|
+
|
|
343
|
+
await ssg.run({
|
|
344
|
+
router: {
|
|
345
|
+
listStaticGenerationRoutes: vi.fn(async () => []),
|
|
346
|
+
} satisfies StaticGenerationRunnerInput['router'],
|
|
347
|
+
baseUrl: 'http://localhost:3000',
|
|
348
|
+
routeRendererFactory: {
|
|
349
|
+
getPageRenderer: vi.fn(),
|
|
350
|
+
getExplicitViewRenderer: vi.fn(() => ({
|
|
351
|
+
renderToResponse,
|
|
352
|
+
})),
|
|
353
|
+
} satisfies StaticGenerationRendererFactory,
|
|
354
|
+
staticRoutes: [
|
|
355
|
+
{
|
|
356
|
+
path: '/blog/[slug]',
|
|
357
|
+
loader: async () => ({
|
|
358
|
+
default: Object.assign(() => null, {
|
|
359
|
+
config: { __eco: testInjectedMeta },
|
|
360
|
+
staticPaths: async () => ({ paths: [{ params: { slug: 'hello-world' } }] }),
|
|
361
|
+
staticProps,
|
|
362
|
+
}),
|
|
363
|
+
}),
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
expect(staticProps).toHaveBeenCalledWith({
|
|
369
|
+
pathname: { params: { slug: 'hello-world' } },
|
|
370
|
+
appConfig: expect.any(Object),
|
|
371
|
+
runtimeOrigin: 'http://localhost:3000',
|
|
372
|
+
});
|
|
373
|
+
expect(renderToResponse).toHaveBeenCalledWith(expect.any(Function), { slug: 'hello-world' }, {});
|
|
374
|
+
expect(writeMock).toHaveBeenCalledWith('/test/project/dist/blog/hello-world.html', '<html>Post</html>');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test('should log an error for dynamic explicit routes without staticPaths', async () => {
|
|
378
|
+
const ssg = new StaticSiteGenerator({
|
|
379
|
+
appConfig: createMockConfig({ baseUrl: 'http://localhost:3000' } as any),
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
await ssg.run({
|
|
383
|
+
router: {
|
|
384
|
+
listStaticGenerationRoutes: vi.fn(async () => []),
|
|
385
|
+
} satisfies StaticGenerationRunnerInput['router'],
|
|
386
|
+
baseUrl: 'http://localhost:3000',
|
|
387
|
+
routeRendererFactory: {
|
|
388
|
+
getPageRenderer: vi.fn(),
|
|
389
|
+
getExplicitViewRenderer: vi.fn(() => ({
|
|
390
|
+
renderToResponse: vi.fn(),
|
|
391
|
+
})),
|
|
392
|
+
} satisfies StaticGenerationRendererFactory,
|
|
393
|
+
staticRoutes: [
|
|
394
|
+
{
|
|
395
|
+
path: '/blog/[slug]',
|
|
396
|
+
loader: async () => ({
|
|
397
|
+
default: Object.assign(() => null, {
|
|
398
|
+
config: { __eco: testInjectedMeta },
|
|
399
|
+
}),
|
|
400
|
+
}),
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
expect(writeMock).not.toHaveBeenCalledWith('/test/project/dist/blog/hello-world.html', expect.anything());
|
|
406
|
+
});
|
|
315
407
|
});
|
|
316
408
|
});
|