@octanejs/vite-plugin 0.1.5 → 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.
@@ -1,14 +0,0 @@
1
- import { defineConfig, RenderRoute } from '@octanejs/vite-plugin';
2
-
3
- export default defineConfig({
4
- router: {
5
- routes: [
6
- new RenderRoute({ path: '/', entry: ['Page', '/src/Page.tsrx'], layout: '/src/Layout.tsrx' }),
7
- new RenderRoute({
8
- path: '/pages/:slug',
9
- entry: ['Page', '/src/Page.tsrx'],
10
- layout: '/src/Layout.tsrx',
11
- }),
12
- ],
13
- },
14
- });
@@ -1,7 +0,0 @@
1
- {
2
- "name": "octane-vite-plugin-fixture-app",
3
- "private": true,
4
- "version": "0.0.0",
5
- "type": "module",
6
- "description": "Minimal app the production-build test builds end-to-end (node_modules is symlinked by the test setup)."
7
- }
@@ -1,6 +0,0 @@
1
- export default function Layout(props: { children: unknown }) @{
2
- <div class="shell">
3
- <nav>{'fixture-nav'}</nav>
4
- {props.children}
5
- </div>
6
- }
@@ -1,17 +0,0 @@
1
- import { useState } from 'octane';
2
-
3
- // A page with a dynamic text hole, a param read, and an event handler — enough
4
- // to prove the server bundle renders hydratable markup (markers + scoped
5
- // state) identical to dev SSR.
6
- export function Page(props: { params: Record<string, string>; url: string }) @{
7
- const [count] = useState(1);
8
- <main>
9
- <h1>
10
- {'Fixture page ' + (props.params.slug ?? 'home')}
11
- </h1>
12
- <p class="url">{props.url}</p>
13
- <p class="count">
14
- {'Count: ' + count}
15
- </p>
16
- </main>
17
- }
@@ -1,12 +0,0 @@
1
- import { defineConfig } from 'vite';
2
- import { octane } from '@octanejs/vite-plugin';
3
-
4
- // SSR module graphs (dev + server build) must see the server runtime for bare
5
- // 'octane' imports from non-compiled sources (none here, but keeps the fixture
6
- // shaped like a real app).
7
- export default defineConfig({
8
- plugins: [octane()],
9
- ssr: {
10
- noExternal: [/^octane($|\/)/],
11
- },
12
- });
@@ -1,134 +0,0 @@
1
- // createHandler unit tests — the production handler's pure assembly decisions
2
- // (template splitting, hydration payload shape, status, preload tags, the
3
- // buffered fallback, server routes, 404) with stub renderers. The real-render
4
- // byte-compat path is covered end-to-end in production.test.ts.
5
- import { describe, it, expect } from 'vitest';
6
- import { createHandler } from '../src/server/production.js';
7
- import { RenderRoute, ServerRoute } from '../src/routes.js';
8
-
9
- const TEMPLATE = `<!doctype html>
10
- <html><head><!--ssr-head--></head><body><div id="root"><!--ssr-body--></div>
11
- <script type="module" src="/assets/hydrate-abc.js"></script></body></html>`;
12
-
13
- function Page() {
14
- return '<main>page</main>';
15
- }
16
-
17
- function streamOf(text: string): ReadableStream<Uint8Array> {
18
- return new ReadableStream({
19
- start(controller) {
20
- controller.enqueue(new TextEncoder().encode(text));
21
- controller.close();
22
- },
23
- });
24
- }
25
-
26
- const baseDeps = {
27
- renderToReadableStream: async () =>
28
- streamOf('<style data-octane="x">.x{}</style><main>page</main>'),
29
- prerender: async () => ({
30
- html: '<main>page</main>',
31
- css: '<style data-octane="x">.x{}</style>',
32
- }),
33
- htmlTemplate: TEMPLATE,
34
- executeServerFunction: async () => '',
35
- };
36
-
37
- function makeManifest(overrides: Record<string, unknown> = {}) {
38
- const routes = [
39
- new RenderRoute({ path: '/', entry: ['Page', '/src/Page.tsrx'] }),
40
- new RenderRoute({ path: '/*splat', entry: ['Page', '/src/Page.tsrx'], status: 404 }),
41
- new ServerRoute({
42
- path: '/api/ping',
43
- handler: () => new Response('pong', { status: 200 }),
44
- }),
45
- ];
46
- return {
47
- routes,
48
- components: { '/src/Page.tsrx': { Page } },
49
- layouts: {},
50
- middlewares: [],
51
- ...overrides,
52
- };
53
- }
54
-
55
- describe('createHandler', () => {
56
- it('streams template prefix → render stream → suffix with the dev-shaped data script', async () => {
57
- const handler = createHandler(makeManifest() as any, baseDeps as any);
58
- const response = await handler(new Request('http://localhost/?q=1'));
59
- expect(response.status).toBe(200);
60
- const html = await response.text();
61
-
62
- // Assembly: styles + markup inside #root, template suffix intact.
63
- expect(html).toContain(
64
- '<div id="root"><style data-octane="x">.x{}</style><main>page</main></div>',
65
- );
66
- expect(html).toContain('src="/assets/hydrate-abc.js"');
67
-
68
- // The payload matches dev render-route.js: same keys, same order.
69
- const payload = html.match(/__octane_data" type="application\/json">(.*?)<\/script>/s)![1];
70
- expect(payload).toBe(
71
- JSON.stringify({
72
- entry: '/src/Page.tsrx',
73
- exportName: 'Page',
74
- layout: null,
75
- routeIndex: 0,
76
- params: {},
77
- url: '/?q=1',
78
- preHydrate: null,
79
- }),
80
- );
81
- });
82
-
83
- it('uses the RenderRoute status (catch-all 404) and route params', async () => {
84
- const handler = createHandler(makeManifest() as any, baseDeps as any);
85
- const response = await handler(new Request('http://localhost/not/a/page'));
86
- expect(response.status).toBe(404);
87
- const html = await response.text();
88
- expect(html).toContain('"params":{"splat":"not/a/page"}');
89
- });
90
-
91
- it("render: 'buffered' awaits prerender and sends one document (css leads the body)", async () => {
92
- let streamed = false;
93
- const deps = {
94
- ...baseDeps,
95
- renderToReadableStream: async () => {
96
- streamed = true;
97
- return streamOf('');
98
- },
99
- };
100
- const handler = createHandler(makeManifest({ render: 'buffered' }) as any, deps as any);
101
- const html = await (await handler(new Request('http://localhost/'))).text();
102
- expect(streamed).toBe(false);
103
- expect(html).toContain(
104
- '<div id="root"><style data-octane="x">.x{}</style><main>page</main></div>',
105
- );
106
- });
107
-
108
- it('emits stylesheet + modulepreload tags for the matched entry from clientAssets', async () => {
109
- const handler = createHandler(
110
- makeManifest({
111
- clientAssets: {
112
- '/src/Page.tsrx': { js: 'assets/Page-123.js', css: ['assets/Page-123.css'] },
113
- },
114
- }) as any,
115
- baseDeps as any,
116
- );
117
- const html = await (await handler(new Request('http://localhost/'))).text();
118
- expect(html).toContain('<link rel="stylesheet" href="/assets/Page-123.css">');
119
- expect(html).toContain('<link rel="modulepreload" href="/assets/Page-123.js">');
120
- });
121
-
122
- it('serves ServerRoutes and 404s unmatched paths when no catch-all exists', async () => {
123
- const manifest = makeManifest();
124
- (manifest.routes as unknown[]).splice(1, 1); // drop the catch-all
125
- const handler = createHandler(manifest as any, baseDeps as any);
126
-
127
- const api = await handler(new Request('http://localhost/api/ping'));
128
- expect(api.status).toBe(200);
129
- expect(await api.text()).toBe('pong');
130
-
131
- const missing = await handler(new Request('http://localhost/nope'));
132
- expect(missing.status).toBe(404);
133
- });
134
- });
@@ -1,155 +0,0 @@
1
- // @octanejs/vite-plugin unit tests — the pure decision logic the website
2
- // surfaced gaps in: the dev-middleware's Vite-owned URL filter, `octane()`
3
- // option forwarding to the bundled compiler, the appType default, and the
4
- // config resolution of `router.preHydrate` / RenderRoute `status`.
5
- import { fileURLToPath } from 'node:url';
6
- import { dirname } from 'node:path';
7
- import { describe, it, expect } from 'vitest';
8
- import { octane, isViteOwnedUrl, resolveOctaneConfig, RenderRoute } from '../src/index.js';
9
- import { RESOLVED_ADAPTER_BROWSER_STUB_ID } from '../src/project-codegen.js';
10
-
11
- function url(u: string): URL {
12
- return new URL(u, 'http://localhost');
13
- }
14
-
15
- // Use this package as the fake Vite root: '/src/index.js' and '/types/index.d.ts'
16
- // are real files under it, '/docs/v2.0' etc. are not.
17
- const PKG_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
18
-
19
- describe('isViteOwnedUrl', () => {
20
- it('skips Vite-internal namespaces and module/asset requests', () => {
21
- expect(isViteOwnedUrl(url('/@vite/client'))).toBe(true);
22
- expect(isViteOwnedUrl(url('/@id/virtual:octane-hydrate'))).toBe(true);
23
- expect(isViteOwnedUrl(url('/@fs/Users/x/repo/src/main.ts'))).toBe(true);
24
- expect(isViteOwnedUrl(url('/__open-in-editor?file=x'))).toBe(true);
25
- expect(isViteOwnedUrl(url('/node_modules/.vite/deps/chunk.js'))).toBe(true);
26
- expect(isViteOwnedUrl(url('/src/main.ts'))).toBe(true);
27
- expect(isViteOwnedUrl(url('/src/app/App.tsrx?v=abc123'))).toBe(true);
28
- expect(isViteOwnedUrl(url('/favicon.svg'))).toBe(true);
29
- expect(isViteOwnedUrl(url('/src/worker?worker'))).toBe(true);
30
- expect(isViteOwnedUrl(url('/src/logo?url'))).toBe(true);
31
- });
32
-
33
- it('keeps page navigations', () => {
34
- expect(isViteOwnedUrl(url('/'))).toBe(false);
35
- expect(isViteOwnedUrl(url('/docs'))).toBe(false);
36
- expect(isViteOwnedUrl(url('/docs/quick-start'))).toBe(false);
37
- expect(isViteOwnedUrl(url('/definitely/not/a/page'))).toBe(false);
38
- expect(isViteOwnedUrl(url('/search?q=octane'))).toBe(false);
39
- // A bare dotfile segment is not an extension.
40
- expect(isViteOwnedUrl(url('/.well-known'))).toBe(false);
41
- // VALUED params matching a marker name are app query strings — Vite's
42
- // transform markers are always bare (`?url`, `?raw`, `&import`).
43
- expect(isViteOwnedUrl(url('/docs?url=https://example.com'))).toBe(false);
44
- expect(isViteOwnedUrl(url('/page?raw=1'))).toBe(false);
45
- expect(isViteOwnedUrl(url('/jobs?worker=nurse'))).toBe(false);
46
- });
47
-
48
- it('with fileRoots, an extension only counts when a real file backs it', () => {
49
- // Real files under the root → Vite's.
50
- expect(isViteOwnedUrl(url('/src/index.js'), [PKG_ROOT])).toBe(true);
51
- expect(isViteOwnedUrl(url('/types/index.d.ts?v=abc'), [PKG_ROOT])).toBe(true);
52
- // Dotted PAGE urls → SSR them.
53
- expect(isViteOwnedUrl(url('/docs/v2.0'), [PKG_ROOT])).toBe(false);
54
- expect(isViteOwnedUrl(url('/users/jane.doe'), [PKG_ROOT])).toBe(false);
55
- // A missing asset also SSRs (the app's 404 page beats a bare dev 404).
56
- expect(isViteOwnedUrl(url('/missing.png'), [PKG_ROOT])).toBe(false);
57
- // Multiple roots (root + publicDir).
58
- expect(isViteOwnedUrl(url('/src/index.js'), ['/nowhere', PKG_ROOT])).toBe(true);
59
- // Non-file checks are unaffected by fileRoots.
60
- expect(isViteOwnedUrl(url('/@vite/client'), [PKG_ROOT])).toBe(true);
61
- expect(isViteOwnedUrl(url('/src/worker?worker'), [PKG_ROOT])).toBe(true);
62
- });
63
- });
64
-
65
- describe('octane() plugin factory', () => {
66
- it('forwards `exclude` to the bundled compiler (hook-slotting skip)', () => {
67
- const [compiler] = octane({ exclude: ['/packages/tanstack-router/src/'] });
68
- const code =
69
- "import { useState } from 'octane';\nexport function useThing() { return useState(0); }\n";
70
- const transform = compiler.transform as (code: string, id: string) => unknown;
71
-
72
- // A pnpm-symlinked binding source resolves to /packages/*/src — excluded,
73
- // so the hand-slot-forwarding file passes through untouched.
74
- expect(transform.call({}, code, '/repo/packages/tanstack-router/src/useRouter.ts')).toBeNull();
75
- // App code is still slotted.
76
- expect(transform.call({}, code, '/repo/src/useThing.ts')).not.toBeNull();
77
- });
78
-
79
- it("defaults appType to 'custom' for dev, but respects the user and `vite preview`", async () => {
80
- const [, meta] = octane();
81
- const config = meta.config as (
82
- userConfig: object,
83
- env: object,
84
- ) => Promise<{ appType?: string }>;
85
-
86
- expect((await config({}, { command: 'serve', mode: 'development' })).appType).toBe('custom');
87
- // An explicit user appType wins.
88
- expect(
89
- (await config({ appType: 'spa' }, { command: 'serve', mode: 'development' })).appType,
90
- ).toBe(undefined);
91
- // `vite preview` serves static files with Vite's own fallback; the
92
- // production SSR build is previewed with `octane-preview` instead.
93
- expect(
94
- (await config({}, { command: 'serve', mode: 'production', isPreview: true })).appType,
95
- ).toBe(undefined);
96
- });
97
- });
98
-
99
- describe('resolveOctaneConfig', () => {
100
- const entry = ['App', '/src/App.tsrx'] as const;
101
-
102
- it('passes router.preHydrate through and validates its shape', () => {
103
- const resolved = resolveOctaneConfig({
104
- router: {
105
- routes: [new RenderRoute({ path: '/', entry })],
106
- preHydrate: '/src/pre-hydrate.ts',
107
- },
108
- });
109
- expect(resolved.router.preHydrate).toBe('/src/pre-hydrate.ts');
110
- // Absent stays absent.
111
- expect(resolveOctaneConfig({}).router.preHydrate).toBe(undefined);
112
- // Must be a Vite-root path the browser can dynamic-import.
113
- expect(() =>
114
- resolveOctaneConfig({ router: { routes: [], preHydrate: 'src/pre-hydrate.ts' } }),
115
- ).toThrow(/preHydrate/);
116
- });
117
-
118
- it('accepts an integer RenderRoute status and rejects anything else', () => {
119
- const route = new RenderRoute({ path: '/*splat', entry, status: 404 });
120
- expect(route.status).toBe(404);
121
- expect(resolveOctaneConfig({ router: { routes: [route] } }).router.routes[0]).toBe(route);
122
- expect(() =>
123
- resolveOctaneConfig({
124
- router: { routes: [new RenderRoute({ path: '/', entry, status: 4.04 })] },
125
- }),
126
- ).toThrow(/status/);
127
- });
128
- });
129
-
130
- describe('server-only adapter browser stub', () => {
131
- const [, meta] = octane();
132
- const resolveId = meta.resolveId as (
133
- id: string,
134
- importer?: string,
135
- options?: { ssr?: boolean },
136
- ) => Promise<string | null>;
137
- const load = meta.load as (id: string) => Promise<string | undefined>;
138
-
139
- it('client-side imports of adapter packages resolve to the stub, server gets the real one', async () => {
140
- for (const id of ['@octanejs/adapter-vercel', '@ripple-ts/adapter-node']) {
141
- expect(await resolveId(id, undefined, { ssr: false })).toBe(RESOLVED_ADAPTER_BROWSER_STUB_ID);
142
- }
143
- expect(await resolveId('@octanejs/adapter-vercel', undefined, { ssr: true })).toBe(null);
144
- });
145
-
146
- it('the stub covers the octane adapter surface with no node builtins', async () => {
147
- const source = (await load(RESOLVED_ADAPTER_BROWSER_STUB_ID)) as string;
148
- // The union of the listed adapters' public names — a client import of any
149
- // of them must resolve (and only throw on USE).
150
- for (const name of ['vercel', 'adapt', 'serve']) {
151
- expect(source).toContain(`export function ${name}`);
152
- }
153
- expect(source).not.toContain('node:');
154
- });
155
- });
@@ -1,157 +0,0 @@
1
- // Production SSR build — end-to-end over the fixture app (tests/_fixtures/app):
2
- // `vite build` must produce BOTH bundles (dist/client assets + the
3
- // self-contained dist/server/entry.js), and the server bundle's handler must
4
- // render a route with hydratable output whose body region and #__octane_data
5
- // payload BYTE-MATCH dev SSR for the same request — that is the contract that
6
- // lets hydrateRoot adopt production responses exactly like dev ones.
7
- //
8
- // The fixture has no installed node_modules (it is not a workspace package);
9
- // the setup symlinks the workspace's octane / @octanejs/vite-plugin / vite in,
10
- // which is exactly what a pnpm install would produce.
11
- import { describe, it, expect, beforeAll, afterAll } from 'vitest';
12
- import fs from 'node:fs';
13
- import path from 'node:path';
14
- import { pathToFileURL, fileURLToPath } from 'node:url';
15
- import { build, createServer, type ViteDevServer } from 'vite';
16
-
17
- const fixtureRoot = fileURLToPath(new URL('./_fixtures/app', import.meta.url));
18
- const packageRoot = fileURLToPath(new URL('../', import.meta.url));
19
- const repoRoot = path.resolve(packageRoot, '../..');
20
- const distDir = path.join(fixtureRoot, 'dist');
21
-
22
- function linkPackage(name: string, target: string) {
23
- const dest = path.join(fixtureRoot, 'node_modules', name);
24
- fs.mkdirSync(path.dirname(dest), { recursive: true });
25
- fs.rmSync(dest, { recursive: true, force: true });
26
- fs.symlinkSync(target, dest, 'dir');
27
- }
28
-
29
- /** The rendered body region: everything streamed into `<div id="root">`. */
30
- function bodyRegionOf(html: string): string {
31
- const open = '<div id="root">';
32
- const start = html.indexOf(open);
33
- const end = html.lastIndexOf('</div>');
34
- expect(start).toBeGreaterThan(-1);
35
- expect(end).toBeGreaterThan(start);
36
- return html.slice(start + open.length, end);
37
- }
38
-
39
- function dataScriptOf(html: string): string {
40
- const match = html.match(/<script id="__octane_data" type="application\/json">(.*?)<\/script>/s);
41
- expect(match).not.toBeNull();
42
- return match![1];
43
- }
44
-
45
- let devServer: ViteDevServer | null = null;
46
- let devOrigin = '';
47
-
48
- beforeAll(async () => {
49
- linkPackage('octane', path.join(repoRoot, 'packages/octane'));
50
- linkPackage('@octanejs/vite-plugin', packageRoot);
51
- linkPackage('vite', path.join(packageRoot, 'node_modules/vite'));
52
-
53
- fs.rmSync(distDir, { recursive: true, force: true });
54
-
55
- // The production build: client bundle, then (closeBundle) the server bundle.
56
- await build({ root: fixtureRoot, logLevel: 'silent' });
57
-
58
- // A dev server on a random port — the byte-compat oracle.
59
- devServer = await createServer({
60
- root: fixtureRoot,
61
- logLevel: 'silent',
62
- server: { port: 0 },
63
- });
64
- await devServer.listen();
65
- const address = devServer.httpServer?.address();
66
- if (!address || typeof address !== 'object') throw new Error('dev server has no address');
67
- devOrigin = `http://localhost:${address.port}`;
68
- }, 180_000);
69
-
70
- afterAll(async () => {
71
- await devServer?.close();
72
- fs.rmSync(distDir, { recursive: true, force: true });
73
- fs.rmSync(path.join(fixtureRoot, 'node_modules'), { recursive: true, force: true });
74
- });
75
-
76
- describe('production SSR build', () => {
77
- it('emits both bundles, moves the template to dist/server, and strips build metadata', () => {
78
- expect(fs.existsSync(path.join(distDir, 'server/entry.js'))).toBe(true);
79
- expect(fs.existsSync(path.join(distDir, 'server/index.html'))).toBe(true);
80
- // The template must NOT stay in the static dir (it would shadow SSR at '/'
81
- // on filesystem-first hosts) and the manifest must not ship.
82
- expect(fs.existsSync(path.join(distDir, 'client/index.html'))).toBe(false);
83
- expect(fs.existsSync(path.join(distDir, 'client/.vite'))).toBe(false);
84
- // The client build produced hashed assets, including the hydrate entry
85
- // referenced by the moved template.
86
- const template = fs.readFileSync(path.join(distDir, 'server/index.html'), 'utf-8');
87
- const scriptSrc = template.match(/<script type="module"[^>]*src="(\/assets\/[^"]+)"/)?.[1];
88
- expect(scriptSrc).toBeTruthy();
89
- expect(fs.existsSync(path.join(distDir, 'client', scriptSrc!))).toBe(true);
90
- // The SSR placeholders survived the client build untouched.
91
- expect(template).toContain('<!--ssr-head-->');
92
- expect(template).toContain('<!--ssr-body-->');
93
- });
94
-
95
- it('the server bundle is self-contained (imports only node builtins)', () => {
96
- const entry = fs.readFileSync(path.join(distDir, 'server/entry.js'), 'utf-8');
97
- const specifiers = [...entry.matchAll(/^import[^'"]*['"]([^'"]+)['"]/gm)].map((m) => m[1]);
98
- expect(specifiers.length).toBeGreaterThan(0);
99
- for (const spec of specifiers) {
100
- expect(spec.startsWith('node:'), `unexpected external import: ${spec}`).toBe(true);
101
- }
102
- });
103
-
104
- it('renders a route through the built handler, byte-matching dev SSR', async () => {
105
- const { handler } = await import(pathToFileURL(path.join(distDir, 'server/entry.js')).href);
106
-
107
- for (const url of ['/', '/pages/hello']) {
108
- const prodResponse = await handler(new Request(`http://localhost${url}`));
109
- expect(prodResponse.status).toBe(200);
110
- expect(prodResponse.headers.get('content-type')).toBe('text/html; charset=utf-8');
111
- const prodHtml = await prodResponse.text();
112
-
113
- const devResponse = await fetch(`${devOrigin}${url}`);
114
- expect(devResponse.status).toBe(200);
115
- const devHtml = await devResponse.text();
116
-
117
- // The hydratable body region and the hydration payload are the
118
- // byte-compat contract between dev and production.
119
- expect(bodyRegionOf(prodHtml)).toBe(bodyRegionOf(devHtml));
120
- expect(dataScriptOf(prodHtml)).toBe(dataScriptOf(devHtml));
121
-
122
- // Sanity: it actually rendered the page.
123
- expect(prodHtml).toContain('fixture-nav');
124
- expect(prodHtml).toContain(url === '/' ? 'Fixture page home' : 'Fixture page hello');
125
- expect(prodHtml).toContain(`<p class="url">${url}</p>`);
126
- }
127
- });
128
-
129
- it('returns 404 for unmatched routes (no catch-all in the fixture)', async () => {
130
- const { handler } = await import(pathToFileURL(path.join(distDir, 'server/entry.js')).href);
131
- const response = await handler(new Request('http://localhost/nope/nothing'));
132
- expect(response.status).toBe(404);
133
- });
134
-
135
- it('nodeHandler bridges the same handler for Node-style serverless wrappers', async () => {
136
- const { nodeHandler } = await import(pathToFileURL(path.join(distDir, 'server/entry.js')).href);
137
- const chunks: Buffer[] = [];
138
- const headers: Record<string, unknown> = {};
139
- const res = {
140
- statusCode: 0,
141
- headersSent: false,
142
- setHeader(key: string, value: unknown) {
143
- headers[key.toLowerCase()] = value;
144
- },
145
- write(chunk: Uint8Array) {
146
- chunks.push(Buffer.from(chunk));
147
- },
148
- end(chunk?: Uint8Array) {
149
- if (chunk) chunks.push(Buffer.from(chunk));
150
- },
151
- };
152
- await nodeHandler({ method: 'GET', url: '/pages/node', headers: { host: 'localhost' } }, res);
153
- expect(res.statusCode).toBe(200);
154
- expect(headers['content-type']).toBe('text/html; charset=utf-8');
155
- expect(Buffer.concat(chunks).toString('utf-8')).toContain('Fixture page node');
156
- });
157
- });
@@ -1,18 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "nodenext",
4
- "moduleResolution": "nodenext",
5
- "target": "es2022",
6
- "lib": ["esnext", "dom", "dom.iterable"],
7
- "noEmit": true,
8
- "strict": true,
9
- "skipLibCheck": true,
10
- "resolveJsonModule": true,
11
- "allowSyntheticDefaultImports": true,
12
- "types": ["node"],
13
- "allowJs": true,
14
- "checkJs": false
15
- },
16
- "include": ["src/**/*", "types/**/*", "tests/**/*.ts"],
17
- "exclude": ["node_modules", "dist", "tests/_fixtures"]
18
- }