Compare commits
4 commits
main
...
fix-netlif
Author | SHA1 | Date | |
---|---|---|---|
|
c77f06e585 | ||
|
3e97151734 | ||
|
cacaeafb9b | ||
|
9fee2fa559 |
22 changed files with 294 additions and 12 deletions
5
.changeset/swift-pigs-shave.md
Normal file
5
.changeset/swift-pigs-shave.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/deno': patch
|
||||
---
|
||||
|
||||
Fix for using Astro.glob when using the Deno Deploy adapter
|
|
@ -22,7 +22,12 @@
|
|||
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
|
||||
"build:ci": "astro-scripts build \"src/**/*.ts\"",
|
||||
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
||||
"test": "deno test --allow-run --allow-read --allow-env --allow-net ./test/"
|
||||
"test:import": "deno test --allow-run --allow-env --allow-read --allow-net --ignore=test/dynamic-import.test.js ./test/",
|
||||
"test:subprocess": "deno test --allow-run --allow-env --allow-net ./test/dynamic-import.test.js",
|
||||
"test": "npm run test:import && npm run test:subprocess"
|
||||
},
|
||||
"dependencies": {
|
||||
"esbuild": "^0.14.42"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "workspace:*",
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import type { AstroAdapter, AstroIntegration } from 'astro';
|
||||
import { fileURLToPath } from 'url';
|
||||
import esbuild from 'esbuild';
|
||||
import * as npath from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
interface Options {
|
||||
port?: number;
|
||||
|
@ -15,14 +19,20 @@ export function getAdapter(args?: Options): AstroAdapter {
|
|||
}
|
||||
|
||||
export default function createIntegration(args?: Options): AstroIntegration {
|
||||
let _buildConfig: any;
|
||||
let _vite: any;
|
||||
return {
|
||||
name: '@astrojs/deno',
|
||||
hooks: {
|
||||
'astro:config:done': ({ setAdapter }) => {
|
||||
setAdapter(getAdapter(args));
|
||||
},
|
||||
'astro:build:start': ({ buildConfig }) => {
|
||||
_buildConfig = buildConfig;
|
||||
},
|
||||
'astro:build:setup': ({ vite, target }) => {
|
||||
if (target === 'server') {
|
||||
_vite = vite;
|
||||
vite.resolve = vite.resolve || {};
|
||||
vite.resolve.alias = vite.resolve.alias || {};
|
||||
|
||||
|
@ -41,6 +51,28 @@ export default function createIntegration(args?: Options): AstroIntegration {
|
|||
};
|
||||
}
|
||||
},
|
||||
'astro:build:done': async () => {
|
||||
const entryUrl = new URL(_buildConfig.serverEntry, _buildConfig.server);
|
||||
const pth = fileURLToPath(entryUrl);
|
||||
await esbuild.build({
|
||||
target: 'es2020',
|
||||
platform: 'browser',
|
||||
entryPoints: [pth],
|
||||
outfile: pth,
|
||||
allowOverwrite: true,
|
||||
format: 'esm',
|
||||
bundle: true,
|
||||
external: [ "@astrojs/markdown-remark"]
|
||||
});
|
||||
|
||||
// Remove chunks, if they exist. Since we have bundled via esbuild these chunks are trash.
|
||||
try {
|
||||
const chunkFileNames = _vite?.build?.rollupOptions?.output?.chunkFileNames ?? 'chunks/chunk.[hash].mjs';
|
||||
const chunkPath = npath.dirname(chunkFileNames);
|
||||
const chunksDirUrl = new URL(chunkPath + '/', _buildConfig.server);
|
||||
await fs.promises.rm(chunksDirUrl, { recursive: true, force: true });
|
||||
} catch {}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,13 +32,15 @@ export function start(manifest: SSRManifest, options: Options) {
|
|||
return fetch(localPath.toString());
|
||||
};
|
||||
|
||||
const port = options.port ?? 8085;
|
||||
_server = new Server({
|
||||
port: options.port ?? 8085,
|
||||
port,
|
||||
hostname: options.hostname ?? '0.0.0.0',
|
||||
handler,
|
||||
});
|
||||
|
||||
_startPromise = _server.listenAndServe();
|
||||
_startPromise = Promise.resolve(_server.listenAndServe());
|
||||
console.error(`Server running on port ${port}`);
|
||||
}
|
||||
|
||||
export function createExports(manifest: SSRManifest, options: Options) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from 'https://deno.land/std@0.110.0/path/mod.ts';
|
||||
export * from 'https://deno.land/std@0.132.0/testing/asserts.ts';
|
||||
export * from 'https://deno.land/x/deno_dom/deno-dom-wasm.ts';
|
||||
export * from 'https://deno.land/std@0.142.0/streams/conversion.ts';
|
||||
|
|
21
packages/integrations/deno/test/dynamic-import.test.js
Normal file
21
packages/integrations/deno/test/dynamic-import.test.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { runBuildAndStartAppFromSubprocess } from './helpers.js';
|
||||
import { assertEquals, assert, DOMParser } from './deps.js';
|
||||
|
||||
async function startApp(cb) {
|
||||
await runBuildAndStartAppFromSubprocess('./fixtures/dynimport/', cb);
|
||||
}
|
||||
|
||||
Deno.test({
|
||||
name: 'Dynamic import',
|
||||
async fn() {
|
||||
await startApp(async () => {
|
||||
const resp = await fetch('http://127.0.0.1:8085/');
|
||||
assertEquals(resp.status, 200);
|
||||
const html = await resp.text();
|
||||
assert(html);
|
||||
const doc = new DOMParser().parseFromString(html, `text/html`);
|
||||
const div = doc.querySelector('#thing');
|
||||
assert(div, 'div exists');
|
||||
});
|
||||
},
|
||||
});
|
9
packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs
vendored
Normal file
9
packages/integrations/deno/test/fixtures/dynimport/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import deno from '@astrojs/deno';
|
||||
|
||||
export default defineConfig({
|
||||
adapter: deno(),
|
||||
experimental: {
|
||||
ssr: true
|
||||
}
|
||||
})
|
9
packages/integrations/deno/test/fixtures/dynimport/package.json
vendored
Normal file
9
packages/integrations/deno/test/fixtures/dynimport/package.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "@test/deno-astro-dynimport",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*",
|
||||
"@astrojs/deno": "workspace:*"
|
||||
}
|
||||
}
|
4
packages/integrations/deno/test/fixtures/dynimport/src/components/Thing.astro
vendored
Normal file
4
packages/integrations/deno/test/fixtures/dynimport/src/components/Thing.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
|
||||
---
|
||||
<div id="thing">testing</div>
|
11
packages/integrations/deno/test/fixtures/dynimport/src/pages/index.astro
vendored
Normal file
11
packages/integrations/deno/test/fixtures/dynimport/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
const { default: Thing } = await import('../components/Thing.astro');
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<Thing />
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +1,4 @@
|
|||
import { fromFileUrl } from './deps.js';
|
||||
import { readableStreamFromReader, fromFileUrl } from './deps.js';
|
||||
const dir = new URL('./', import.meta.url);
|
||||
|
||||
export async function runBuild(fixturePath) {
|
||||
|
@ -10,14 +10,52 @@ export async function runBuild(fixturePath) {
|
|||
return async () => await proc.close();
|
||||
}
|
||||
|
||||
export async function runBuildAndStartApp(fixturePath, cb) {
|
||||
const url = new URL(fixturePath, dir);
|
||||
const close = await runBuild(fixturePath);
|
||||
const mod = await import(new URL('./dist/server/entry.mjs', url));
|
||||
export async function startModFromImport(baseUrl) {
|
||||
const entryUrl = new URL('./dist/server/entry.mjs', baseUrl);
|
||||
const mod = await import(entryUrl);
|
||||
|
||||
if (!mod.running()) {
|
||||
mod.start();
|
||||
}
|
||||
|
||||
return () => mod.stop();
|
||||
}
|
||||
|
||||
export async function startModFromSubprocess(baseUrl) {
|
||||
const entryUrl = new URL('./dist/server/entry.mjs', baseUrl);
|
||||
let proc = Deno.run({
|
||||
cmd: ['deno', 'run', '--allow-env', '--allow-net', fromFileUrl(entryUrl)],
|
||||
cwd: fromFileUrl(baseUrl),
|
||||
stderr: 'piped'
|
||||
});
|
||||
const stderr = readableStreamFromReader(proc.stderr);
|
||||
const dec = new TextDecoder();
|
||||
for await(let bytes of stderr) {
|
||||
let msg = dec.decode(bytes);
|
||||
if(msg.includes(`Server running`)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return () => proc.close();
|
||||
}
|
||||
|
||||
export async function runBuildAndStartApp(fixturePath, cb) {
|
||||
const url = new URL(fixturePath, dir);
|
||||
const close = await runBuild(fixturePath);
|
||||
const stop = await startModFromImport(url);
|
||||
|
||||
await cb();
|
||||
await mod.stop();
|
||||
await stop();
|
||||
await close();
|
||||
}
|
||||
|
||||
|
||||
export async function runBuildAndStartAppFromSubprocess(fixturePath, cb) {
|
||||
const url = new URL(fixturePath, dir);
|
||||
const close = await runBuild(fixturePath);
|
||||
const stop = await startModFromSubprocess(url);
|
||||
|
||||
await cb();
|
||||
await stop();
|
||||
await close();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
"test": "npm run test-fn"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/webapi": "^0.12.0"
|
||||
"@astrojs/webapi": "^0.12.0",
|
||||
"esbuild": "^0.14.42"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@netlify/edge-handler-types": "^0.34.1",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import type { AstroAdapter, AstroIntegration, AstroConfig, RouteData } from 'astro';
|
||||
import type { AstroAdapter, AstroIntegration, AstroConfig, RouteData, BuildConfig } from 'astro';
|
||||
import { createRedirects } from './shared.js';
|
||||
import esbuild from 'esbuild';
|
||||
import * as fs from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import * as npath from 'path';
|
||||
|
||||
export function getAdapter(): AstroAdapter {
|
||||
return {
|
||||
|
@ -62,9 +65,34 @@ async function createEdgeManifest(routes: RouteData[], entryFile: string, dir: U
|
|||
await fs.promises.writeFile(manifestURL, _manifest, 'utf-8');
|
||||
}
|
||||
|
||||
async function bundleServerEntry(buildConfig: BuildConfig, vite: any) {
|
||||
const entryUrl = new URL(buildConfig.serverEntry, buildConfig.server);
|
||||
const pth = fileURLToPath(entryUrl);
|
||||
await esbuild.build({
|
||||
target: 'es2020',
|
||||
platform: 'browser',
|
||||
entryPoints: [pth],
|
||||
outfile: pth,
|
||||
allowOverwrite: true,
|
||||
format: 'esm',
|
||||
bundle: true,
|
||||
external: [ "@astrojs/markdown-remark"]
|
||||
});
|
||||
|
||||
// Remove chunks, if they exist. Since we have bundled via esbuild these chunks are trash.
|
||||
try {
|
||||
const chunkFileNames = vite?.build?.rollupOptions?.output?.chunkFileNames ?? 'chunks/chunk.[hash].mjs';
|
||||
const chunkPath = npath.dirname(chunkFileNames);
|
||||
const chunksDirUrl = new URL(chunkPath + '/', buildConfig.server);
|
||||
await fs.promises.rm(chunksDirUrl, { recursive: true, force: true });
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export function netlifyEdgeFunctions({ dist }: NetlifyEdgeFunctionsOptions = {}): AstroIntegration {
|
||||
let _config: AstroConfig;
|
||||
let entryFile: string;
|
||||
let _buildConfig: BuildConfig;
|
||||
let _vite: any;
|
||||
return {
|
||||
name: '@astrojs/netlify/edge-functions',
|
||||
hooks: {
|
||||
|
@ -80,6 +108,7 @@ export function netlifyEdgeFunctions({ dist }: NetlifyEdgeFunctionsOptions = {})
|
|||
_config = config;
|
||||
},
|
||||
'astro:build:start': async ({ buildConfig }) => {
|
||||
_buildConfig = buildConfig;
|
||||
entryFile = buildConfig.serverEntry.replace(/\.m?js/, '');
|
||||
buildConfig.client = _config.outDir;
|
||||
buildConfig.server = new URL('./.netlify/edge-functions/', _config.root);
|
||||
|
@ -87,6 +116,7 @@ export function netlifyEdgeFunctions({ dist }: NetlifyEdgeFunctionsOptions = {})
|
|||
},
|
||||
'astro:build:setup': ({ vite, target }) => {
|
||||
if (target === 'server') {
|
||||
_vite = vite;
|
||||
vite.resolve = vite.resolve || {};
|
||||
vite.resolve.alias = vite.resolve.alias || {};
|
||||
|
||||
|
@ -106,6 +136,7 @@ export function netlifyEdgeFunctions({ dist }: NetlifyEdgeFunctionsOptions = {})
|
|||
}
|
||||
},
|
||||
'astro:build:done': async ({ routes, dir }) => {
|
||||
await bundleServerEntry(_buildConfig, _vite);
|
||||
await createEdgeManifest(routes, entryFile, _config.root);
|
||||
await createRedirects(routes, dir, entryFile, true);
|
||||
},
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
export { fromFileUrl } from 'https://deno.land/std@0.110.0/path/mod.ts';
|
||||
export { assertEquals, assert } from 'https://deno.land/std@0.132.0/testing/asserts.ts';
|
||||
export * from 'https://deno.land/x/deno_dom/deno-dom-wasm.ts';
|
||||
export * from 'https://deno.land/std@0.142.0/streams/conversion.ts';
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// @ts-ignore
|
||||
import { runBuild, runApp } from './test-utils.ts';
|
||||
// @ts-ignore
|
||||
import { assertEquals, assert, DOMParser } from './deps.ts';
|
||||
|
||||
// @ts-ignore
|
||||
Deno.test({
|
||||
name: 'Dynamic imports',
|
||||
async fn() {
|
||||
let close = await runBuild('./fixtures/dynimport/');
|
||||
let stop = await runApp('./fixtures/dynimport/prod.js');
|
||||
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:8085/');
|
||||
assertEquals(response.status, 200);
|
||||
const html = await response.text();
|
||||
|
||||
assert(html, 'got some html');
|
||||
const doc = new DOMParser().parseFromString(html, `text/html`);
|
||||
const div = doc.querySelector('#thing');
|
||||
assert(div, 'div exists')
|
||||
} finally {
|
||||
await close();
|
||||
await stop();
|
||||
}
|
||||
},
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import { netlifyEdgeFunctions } from '@astrojs/netlify';
|
||||
|
||||
export default defineConfig({
|
||||
adapter: netlifyEdgeFunctions({
|
||||
dist: new URL('./dist/', import.meta.url),
|
||||
}),
|
||||
experimental: {
|
||||
ssr: true
|
||||
}
|
||||
})
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "@test/netlify-edge-astro-dynimport",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*",
|
||||
"@astrojs/netlify": "workspace:*"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import handler from './.netlify/edge-functions/entry.js';
|
||||
import { Server } from 'https://deno.land/std@0.132.0/http/server.ts';
|
||||
|
||||
const _server = new Server({
|
||||
port: 8085,
|
||||
hostname: '0.0.0.0',
|
||||
handler,
|
||||
});
|
||||
|
||||
_server.listenAndServe();
|
||||
console.error(`Server running on port 8085`);
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
|
||||
---
|
||||
<div id="thing">testing</div>
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
const { default: Thing } = await import('../components/Thing.astro');
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<Thing />
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,5 @@
|
|||
// @ts-ignore
|
||||
import { fromFileUrl } from './deps.ts';
|
||||
import { fromFileUrl, readableStreamFromReader } from './deps.ts';
|
||||
const dir = new URL('./', import.meta.url);
|
||||
|
||||
export async function runBuild(fixturePath: string) {
|
||||
|
@ -11,3 +11,21 @@ export async function runBuild(fixturePath: string) {
|
|||
await proc.status();
|
||||
return async () => await proc.close();
|
||||
}
|
||||
|
||||
export async function runApp(entryPath: string) {
|
||||
const entryUrl = new URL(entryPath, dir)
|
||||
let proc = Deno.run({
|
||||
cmd: ['deno', 'run', '--allow-env', '--allow-net', fromFileUrl(entryUrl)],
|
||||
//cwd: fromFileUrl(entryUrl),
|
||||
stderr: 'piped'
|
||||
});
|
||||
const stderr = readableStreamFromReader(proc.stderr);
|
||||
const dec = new TextDecoder();
|
||||
for await(let bytes of stderr) {
|
||||
let msg = dec.decode(bytes);
|
||||
if(msg.includes(`Server running`)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return () => proc.close();
|
||||
}
|
||||
|
|
|
@ -1645,6 +1645,9 @@ importers:
|
|||
specifiers:
|
||||
astro: workspace:*
|
||||
astro-scripts: workspace:*
|
||||
esbuild: ^0.14.42
|
||||
dependencies:
|
||||
esbuild: 0.14.42
|
||||
devDependencies:
|
||||
astro: link:../../astro
|
||||
astro-scripts: link:../../../scripts
|
||||
|
@ -1659,6 +1662,14 @@ importers:
|
|||
'@astrojs/react': link:../../../../react
|
||||
astro: link:../../../../../astro
|
||||
|
||||
packages/integrations/deno/test/fixtures/dynimport:
|
||||
specifiers:
|
||||
'@astrojs/deno': workspace:*
|
||||
astro: workspace:*
|
||||
dependencies:
|
||||
'@astrojs/deno': link:../../..
|
||||
astro: link:../../../../../astro
|
||||
|
||||
packages/integrations/lit:
|
||||
specifiers:
|
||||
'@lit-labs/ssr': ^2.2.0
|
||||
|
@ -1681,14 +1692,24 @@ importers:
|
|||
'@netlify/functions': ^1.0.0
|
||||
astro: workspace:*
|
||||
astro-scripts: workspace:*
|
||||
esbuild: ^0.14.42
|
||||
dependencies:
|
||||
'@astrojs/webapi': link:../../webapi
|
||||
esbuild: 0.14.42
|
||||
devDependencies:
|
||||
'@netlify/edge-handler-types': 0.34.1
|
||||
'@netlify/functions': 1.0.0
|
||||
astro: link:../../astro
|
||||
astro-scripts: link:../../../scripts
|
||||
|
||||
packages/integrations/netlify/test/edge-functions/fixtures/dynimport:
|
||||
specifiers:
|
||||
'@astrojs/netlify': workspace:*
|
||||
astro: workspace:*
|
||||
dependencies:
|
||||
'@astrojs/netlify': link:../../../..
|
||||
astro: link:../../../../../../astro
|
||||
|
||||
packages/integrations/netlify/test/edge-functions/fixtures/edge-basic:
|
||||
specifiers:
|
||||
'@astrojs/netlify': workspace:*
|
||||
|
|
Loading…
Reference in a new issue