summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/blue-rocks-smoke.md18
-rw-r--r--packages/astro/package.json3
-rw-r--r--packages/astro/src/@types/astro.ts6
-rw-r--r--packages/astro/src/core/app/types.ts2
-rw-r--r--packages/astro/src/core/build/common.ts13
-rw-r--r--packages/astro/src/core/build/generate.ts7
-rw-r--r--packages/astro/src/core/build/index.ts12
-rw-r--r--packages/astro/src/core/build/static-build.ts16
-rw-r--r--packages/astro/src/core/build/vite-plugin-ssr.ts7
-rw-r--r--packages/astro/src/core/dev/index.ts3
-rw-r--r--packages/astro/src/core/logger.ts11
-rw-r--r--packages/astro/src/integrations/index.ts6
-rw-r--r--packages/integrations/netlify/package.json34
-rw-r--r--packages/integrations/netlify/readme.md44
-rw-r--r--packages/integrations/netlify/src/index.ts64
-rw-r--r--packages/integrations/netlify/src/integration-functions.ts3
-rw-r--r--packages/integrations/netlify/src/netlify-functions.ts43
-rw-r--r--packages/integrations/netlify/tsconfig.json10
-rw-r--r--pnpm-lock.yaml24
19 files changed, 290 insertions, 36 deletions
diff --git a/.changeset/blue-rocks-smoke.md b/.changeset/blue-rocks-smoke.md
new file mode 100644
index 000000000..bb3bbbf1c
--- /dev/null
+++ b/.changeset/blue-rocks-smoke.md
@@ -0,0 +1,18 @@
+---
+'astro': patch
+'@astrojs/netlify': patch
+'@astrojs/node': patch
+---
+
+Netlify Adapter
+
+This change adds a Netlify adapter that uses Netlify Functions. You can use it like so:
+
+```js
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify';
+
+export default defineConfig({
+ adapter: netlify()
+});
+```
diff --git a/packages/astro/package.json b/packages/astro/package.json
index f6ce9f493..23926f8d0 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -15,6 +15,9 @@
"types": "./dist/types/@types/astro.d.ts",
"typesVersions": {
"*": {
+ "app": [
+ "./dist/types/core/app/index"
+ ],
"app/*": [
"./dist/types/core/app/*"
]
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 9e83af22d..988bec9b0 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -39,6 +39,9 @@ export interface CLIFlags {
}
export interface BuildConfig {
+ client: URL;
+ server: URL;
+ serverEntry: string;
staticMode: boolean | undefined;
}
@@ -617,6 +620,7 @@ export interface AstroAdapter {
name: string;
serverEntrypoint?: string;
exports?: string[];
+ args?: any;
}
export interface EndpointOutput<Output extends Body = Body> {
@@ -670,7 +674,7 @@ export interface AstroIntegration {
'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise<void>;
'astro:server:done'?: () => void | Promise<void>;
'astro:build:start'?: (options: { buildConfig: BuildConfig }) => void | Promise<void>;
- 'astro:build:done'?: (options: { pages: { pathname: string }[]; dir: URL }) => void | Promise<void>;
+ 'astro:build:done'?: (options: { pages: { pathname: string }[]; dir: URL; routes: RouteData[] }) => void | Promise<void>;
};
}
diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts
index ea4bd9cc0..0d395c776 100644
--- a/packages/astro/src/core/app/types.ts
+++ b/packages/astro/src/core/app/types.ts
@@ -27,3 +27,5 @@ export interface SSRManifest {
export type SerializedSSRManifest = Omit<SSRManifest, 'routes'> & {
routes: SerializedRouteInfo[];
};
+
+export type AdapterCreateExports<T = any> = (manifest: SSRManifest, args?: T) => Record<string, any>;
diff --git a/packages/astro/src/core/build/common.ts b/packages/astro/src/core/build/common.ts
index 074170762..5407f66fd 100644
--- a/packages/astro/src/core/build/common.ts
+++ b/packages/astro/src/core/build/common.ts
@@ -1,5 +1,4 @@
import type { AstroConfig, RouteType } from '../../@types/astro';
-import type { StaticBuildOptions } from './types';
import npath from 'path';
import { appendForwardSlash } from '../../core/path.js';
@@ -9,18 +8,6 @@ export function getOutRoot(astroConfig: AstroConfig): URL {
return new URL('./', astroConfig.dist);
}
-export function getServerRoot(astroConfig: AstroConfig): URL {
- const rootFolder = getOutRoot(astroConfig);
- const serverFolder = new URL('./server/', rootFolder);
- return serverFolder;
-}
-
-export function getClientRoot(astroConfig: AstroConfig): URL {
- const rootFolder = getOutRoot(astroConfig);
- const serverFolder = new URL('./client/', rootFolder);
- return serverFolder;
-}
-
export function getOutFolder(astroConfig: AstroConfig, pathname: string, routeType: RouteType): URL {
const outRoot = getOutRoot(astroConfig);
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index b4e77a9e0..119274e76 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -13,7 +13,7 @@ import { BEFORE_HYDRATION_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { call as callEndpoint } from '../endpoint/index.js';
import { render } from '../render/core.js';
import { createLinkStylesheetElementSet, createModuleScriptElementWithSrcSet } from '../render/ssr-element.js';
-import { getOutFile, getOutRoot, getOutFolder, getServerRoot } from './common.js';
+import { getOutFile, getOutRoot, getOutFolder } from './common.js';
import { getPageDataByComponent, eachPageData } from './internal.js';
import { bgMagenta, black, cyan, dim, magenta } from 'kleur/colors';
import { getTimeStat } from './util.js';
@@ -70,8 +70,9 @@ export async function generatePages(result: RollupOutput, opts: StaticBuildOptio
info(opts.logging, null, `\n${bgMagenta(black(' generating static routes '))}\n`);
const ssr = !!opts.astroConfig._ctx.adapter?.serverEntrypoint;
- const outFolder = ssr ? getServerRoot(opts.astroConfig) : getOutRoot(opts.astroConfig);
- const ssrEntryURL = new URL(`./entry.mjs?time=${Date.now()}`, outFolder);
+ const serverEntry = opts.buildConfig.serverEntry;
+ const outFolder = ssr ? opts.buildConfig.server : opts.astroConfig.dist;
+ const ssrEntryURL = new URL('./' + serverEntry + `?time=${Date.now()}`, outFolder);
const ssrEntry = await import(ssrEntryURL.toString());
for (const pageData of eachPageData(internals)) {
diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts
index d830eb88d..14950b2f9 100644
--- a/packages/astro/src/core/build/index.ts
+++ b/packages/astro/src/core/build/index.ts
@@ -7,7 +7,7 @@ import { apply as applyPolyfill } from '../polyfill.js';
import { performance } from 'perf_hooks';
import * as vite from 'vite';
import { createVite, ViteConfigWithSSR } from '../create-vite.js';
-import { debug, defaultLogOptions, info, levels, timerMessage, warn } from '../logger.js';
+import { debug, defaultLogOptions, info, levels, timerMessage, warn, warnIfUsingExperimentalSSR } from '../logger.js';
import { createRouteManifest } from '../routing/index.js';
import { generateSitemap } from '../render/sitemap.js';
import { collectPagesData } from './page-data.js';
@@ -73,11 +73,17 @@ class AstroBuilder {
{ astroConfig: this.config, logging, mode: 'build' }
);
await runHookConfigDone({ config: this.config });
+ warnIfUsingExperimentalSSR(logging, this.config);
this.viteConfig = viteConfig;
const viteServer = await vite.createServer(viteConfig);
this.viteServer = viteServer;
debug('build', timerMessage('Vite started', timer.viteStart));
- const buildConfig: BuildConfig = { staticMode: undefined };
+ const buildConfig: BuildConfig = {
+ client: new URL('./client/', this.config.dist),
+ server: new URL('./server/', this.config.dist),
+ serverEntry: 'entry.mjs',
+ staticMode: undefined
+ };
await runHookBuildStart({ config: this.config, buildConfig });
info(this.logging, 'build', 'Collecting page data...');
@@ -167,7 +173,7 @@ class AstroBuilder {
// You're done! Time to clean up.
await viteServer.close();
- await runHookBuildDone({ config: this.config, pages: pageNames });
+ await runHookBuildDone({ config: this.config, pages: pageNames, routes: Object.values(allPages).map(pd => pd.route) });
if (logging.level && levels[logging.level] <= levels['info']) {
const buildMode = this.config.buildOptions.experimentalSsr ? 'ssr' : 'static';
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 337bc1d59..2e54891d3 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -19,7 +19,6 @@ import { vitePluginSSR } from './vite-plugin-ssr.js';
import { vitePluginPages } from './vite-plugin-pages.js';
import { generatePages } from './generate.js';
import { trackPageData } from './internal.js';
-import { getClientRoot, getServerRoot, getOutRoot } from './common.js';
import { isBuildingToSSR } from '../util.js';
import { getTimeStat } from './util.js';
@@ -114,7 +113,7 @@ export async function staticBuild(opts: StaticBuildOptions) {
async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, input: Set<string>) {
const { astroConfig, viteConfig } = opts;
const ssr = astroConfig.buildOptions.experimentalSsr;
- const out = ssr ? getServerRoot(astroConfig) : getOutRoot(astroConfig);
+ const out = ssr ? opts.buildConfig.server : astroConfig.dist;
// TODO: use vite.mergeConfig() here?
return await vite.build({
logLevel: 'error',
@@ -130,9 +129,10 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
input: [],
output: {
format: 'esm',
- entryFileNames: 'entry.mjs',
+ entryFileNames: opts.buildConfig.serverEntry,
chunkFileNames: 'chunks/chunk.[hash].mjs',
assetFileNames: 'assets/asset.[hash][extname]',
+ inlineDynamicImports: true,
},
},
// must match an esbuild target
@@ -170,12 +170,11 @@ async function clientBuild(opts: StaticBuildOptions, internals: BuildInternals,
return null;
}
- const out = astroConfig.buildOptions.experimentalSsr ? getClientRoot(astroConfig) : getOutRoot(astroConfig);
-
// TODO: use vite.mergeConfig() here?
-
info(opts.logging, null, `\n${bgGreen(black(' building resources '))}\n`);
+ const out = isBuildingToSSR(astroConfig) ? opts.buildConfig.client : astroConfig.dist;
+
const buildResult = await vite.build({
logLevel: 'info',
mode: 'production',
@@ -229,9 +228,8 @@ async function cleanSsrOutput(opts: StaticBuildOptions) {
async function ssrMoveAssets(opts: StaticBuildOptions) {
info(opts.logging, 'build', 'Rearranging server assets...');
- const { astroConfig } = opts;
- const serverRoot = getServerRoot(astroConfig);
- const clientRoot = getClientRoot(astroConfig);
+ const serverRoot = opts.buildConfig.staticMode ? opts.buildConfig.client : opts.buildConfig.server;
+ const clientRoot = opts.buildConfig.client;
const serverAssets = new URL('./assets/', serverRoot);
const clientAssets = new URL('./assets/', clientRoot);
const files = await glob('assets/**/*', {
diff --git a/packages/astro/src/core/build/vite-plugin-ssr.ts b/packages/astro/src/core/build/vite-plugin-ssr.ts
index 692d21741..efa54cc01 100644
--- a/packages/astro/src/core/build/vite-plugin-ssr.ts
+++ b/packages/astro/src/core/build/vite-plugin-ssr.ts
@@ -35,23 +35,24 @@ const _manifest = Object.assign(_deserializeManifest('${manifestReplace}'), {
pageMap: _main.pageMap,
renderers: _main.renderers
});
+const _args = ${adapter.args ? JSON.stringify(adapter.args) : 'undefined'};
${
adapter.exports
- ? `const _exports = adapter.createExports(_manifest);
+ ? `const _exports = adapter.createExports(_manifest, _args);
${adapter.exports.map((name) => `export const ${name} = _exports['${name}'];`).join('\n')}
`
: ''
}
const _start = 'start';
if(_start in adapter) {
- adapter[_start](_manifest);
+ adapter[_start](_manifest, _args);
}`;
}
return void 0;
},
- generateBundle(opts, bundle) {
+ generateBundle(_opts, bundle) {
const manifest = buildManifest(buildOpts, internals);
for (const [_chunkName, chunk] of Object.entries(bundle)) {
diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts
index ca34b0b15..166009cda 100644
--- a/packages/astro/src/core/dev/index.ts
+++ b/packages/astro/src/core/dev/index.ts
@@ -4,7 +4,7 @@ import * as vite from 'vite';
import type { AstroConfig } from '../../@types/astro';
import { runHookConfigDone, runHookConfigSetup, runHookServerDone, runHookServerSetup, runHookServerStart } from '../../integrations/index.js';
import { createVite } from '../create-vite.js';
-import { defaultLogOptions, info, LogOptions, warn } from '../logger.js';
+import { defaultLogOptions, info, LogOptions, warn, warnIfUsingExperimentalSSR } from '../logger.js';
import * as msg from '../messages.js';
import { apply as applyPolyfill } from '../polyfill.js';
import { getResolvedHostForVite } from './util.js';
@@ -32,6 +32,7 @@ export default async function dev(config: AstroConfig, options: DevOptions = { l
{ astroConfig: config, logging: options.logging, mode: 'dev' }
);
await runHookConfigDone({ config });
+ warnIfUsingExperimentalSSR(options.logging, config);
const viteServer = await vite.createServer(viteConfig);
runHookServerSetup({ config, server: viteServer });
await viteServer.listen(config.devOptions.port);
diff --git a/packages/astro/src/core/logger.ts b/packages/astro/src/core/logger.ts
index 19f07316a..75a1e36fe 100644
--- a/packages/astro/src/core/logger.ts
+++ b/packages/astro/src/core/logger.ts
@@ -1,3 +1,4 @@
+import type { AstroConfig } from '../@types/astro';
import { bold, cyan, dim, red, yellow, reset } from 'kleur/colors';
import { performance } from 'perf_hooks';
import { Writable } from 'stream';
@@ -5,6 +6,7 @@ import stringWidth from 'string-width';
import * as readline from 'readline';
import debugPackage from 'debug';
import { format as utilFormat } from 'util';
+import { isBuildingToSSR } from './util.js';
type ConsoleStream = Writable & {
fd: 1 | 2;
@@ -211,3 +213,12 @@ export function timerMessage(message: string, startTime: number = performance.no
let timeDisplay = timeDiff < 750 ? `${Math.round(timeDiff)}ms` : `${(timeDiff / 1000).toFixed(1)}s`;
return `${message} ${dim(timeDisplay)}`;
}
+
+/**
+ * A warning that SSR is experimental. Remove when we can.
+ */
+export function warnIfUsingExperimentalSSR(opts: LogOptions, config: AstroConfig) {
+ if(isBuildingToSSR(config)) {
+ warn(opts, 'warning', bold(`Warning:`), ` SSR support is still experimental and subject to API changes. If using in production pin your dependencies to prevent accidental breakage.`);
+ }
+}
diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts
index 788a8d179..15ab427ea 100644
--- a/packages/astro/src/integrations/index.ts
+++ b/packages/astro/src/integrations/index.ts
@@ -1,6 +1,6 @@
import type { AddressInfo } from 'net';
import type { ViteDevServer } from 'vite';
-import { AstroConfig, AstroRenderer, BuildConfig } from '../@types/astro.js';
+import { AstroConfig, AstroRenderer, BuildConfig, RouteData } from '../@types/astro.js';
import { mergeConfig } from '../core/config.js';
import ssgAdapter from '../adapter-ssg/index.js';
@@ -91,10 +91,10 @@ export async function runHookBuildStart({ config, buildConfig }: { config: Astro
}
}
-export async function runHookBuildDone({ config, pages }: { config: AstroConfig; pages: string[] }) {
+export async function runHookBuildDone({ config, pages, routes }: { config: AstroConfig; pages: string[], routes: RouteData[] }) {
for (const integration of config.integrations) {
if (integration.hooks['astro:build:done']) {
- await integration.hooks['astro:build:done']({ pages: pages.map((p) => ({ pathname: p })), dir: config.dist });
+ await integration.hooks['astro:build:done']({ pages: pages.map((p) => ({ pathname: p })), dir: config.dist, routes });
}
}
}
diff --git a/packages/integrations/netlify/package.json b/packages/integrations/netlify/package.json
new file mode 100644
index 000000000..e3f1fd0ec
--- /dev/null
+++ b/packages/integrations/netlify/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@astrojs/netlify",
+ "description": "Deploy your site to Netlify",
+ "version": "0.0.1",
+ "type": "module",
+ "types": "./dist/index.d.ts",
+ "author": "withastro",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/withastro/astro.git",
+ "directory": "packages/integrations/netlify"
+ },
+ "bugs": "https://github.com/withastro/astro/issues",
+ "homepage": "https://astro.build",
+ "exports": {
+ ".": "./dist/index.js",
+ "./functions": "./dist/integration-functions.js",
+ "./netlify-functions.js": "./dist/netlify-functions.js",
+ "./package.json": "./package.json"
+ },
+ "scripts": {
+ "build": "astro-scripts build \"src/**/*.ts\" && tsc",
+ "dev": "astro-scripts dev \"src/**/*.ts\""
+ },
+ "dependencies": {
+ "@astrojs/webapi": "^0.11.0"
+ },
+ "devDependencies": {
+ "@netlify/functions": "^1.0.0",
+ "astro": "workspace:*",
+ "astro-scripts": "workspace:*"
+ }
+}
diff --git a/packages/integrations/netlify/readme.md b/packages/integrations/netlify/readme.md
new file mode 100644
index 000000000..24fdb5187
--- /dev/null
+++ b/packages/integrations/netlify/readme.md
@@ -0,0 +1,44 @@
+# @astrojs/netlify
+
+Deploy your server-side rendered (SSR) Astro app to [Netlify](https://www.netlify.com/).
+
+Use this adapter in your Astro configuration file:
+
+```js
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/functions';
+
+export default defineConfig({
+ adapter: netlify()
+});
+```
+
+After you build your site the `netlify/` folder will contain [Netlify Functions](https://docs.netlify.com/functions/overview/) in the `netlify/functions/` folder.
+
+Now you can deploy!
+
+```shell
+netlify deploy
+```
+
+## Configuration
+
+The output folder is configuration with the `dist` property when creating the adapter.
+
+```js
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/functions';
+
+export default defineConfig({
+ adapter: netlify({
+ dist: new URL('./dist/', import.meta.url)
+ })
+});
+```
+
+And then point to the dist in your `netlify.toml`:
+
+```toml
+[functions]
+ directory = "dist/functions"
+```
diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts
new file mode 100644
index 000000000..4ddacfaf2
--- /dev/null
+++ b/packages/integrations/netlify/src/index.ts
@@ -0,0 +1,64 @@
+import type { AstroAdapter, AstroIntegration, AstroConfig } from 'astro';
+import fs from 'fs';
+
+export function getAdapter(site: string | undefined): AstroAdapter {
+ return {
+ name: '@astrojs/netlify',
+ serverEntrypoint: '@astrojs/netlify/netlify-functions.js',
+ exports: ['handler'],
+ args: { site }
+ };
+}
+
+interface NetlifyFunctionsOptions {
+ dist?: URL;
+}
+
+function netlifyFunctions({ dist }: NetlifyFunctionsOptions = {}): AstroIntegration {
+ let _config: AstroConfig;
+ let entryFile: string;
+ return {
+ name: '@astrojs/netlify',
+ hooks: {
+ 'astro:config:setup': ({ config }) => {
+ if(dist) {
+ config.dist = dist;
+ } else {
+ config.dist = new URL('./netlify/', config.projectRoot);
+ }
+ },
+ 'astro:config:done': ({ config, setAdapter }) => {
+ setAdapter(getAdapter(config.buildOptions.site));
+ _config = config;
+ },
+ 'astro:build:start': async({ buildConfig }) => {
+ entryFile = buildConfig.serverEntry.replace(/\.m?js/, '');
+ buildConfig.client = _config.dist;
+ buildConfig.server = new URL('./functions/', _config.dist);
+ },
+ 'astro:build:done': async ({ routes, dir }) => {
+ const _redirectsURL = new URL('./_redirects', dir);
+
+ // Create the redirects file that is used for routing.
+ let _redirects = '';
+ for(const route of routes) {
+ if(route.pathname) {
+ _redirects += `
+${route.pathname} /.netlify/functions/${entryFile} 200`
+ }
+ }
+
+ if(fs.existsSync(_redirects)) {
+ await fs.promises.appendFile(_redirectsURL, _redirects, 'utf-8');
+ } else {
+ await fs.promises.writeFile(_redirectsURL, _redirects, 'utf-8');
+ }
+ }
+ },
+ };
+}
+
+export {
+ netlifyFunctions,
+ netlifyFunctions as default
+};
diff --git a/packages/integrations/netlify/src/integration-functions.ts b/packages/integrations/netlify/src/integration-functions.ts
new file mode 100644
index 000000000..540fcdee2
--- /dev/null
+++ b/packages/integrations/netlify/src/integration-functions.ts
@@ -0,0 +1,3 @@
+export {
+ netlifyFunctions as default
+} from './index.js';
diff --git a/packages/integrations/netlify/src/netlify-functions.ts b/packages/integrations/netlify/src/netlify-functions.ts
new file mode 100644
index 000000000..cf6c871a9
--- /dev/null
+++ b/packages/integrations/netlify/src/netlify-functions.ts
@@ -0,0 +1,43 @@
+import { SSRManifest } from 'astro';
+import type { Handler } from "@netlify/functions";
+import { App } from 'astro/app';
+import { polyfill } from '@astrojs/webapi';
+
+polyfill(globalThis, {
+ exclude: 'window document',
+});
+
+interface Args {
+ site?: string;
+}
+
+export const createExports = (manifest: SSRManifest, args: Args) => {
+ const app = new App(manifest);
+ const site = new URL(args.site ?? `https://netlify.com`);
+
+ const handler: Handler = async (event) => {
+ const headers = new Headers(event.headers as any);
+ const request = new Request(new URL(event.path, site).toString(), {
+ method: event.httpMethod,
+ headers
+ });
+
+ if(!app.match(request)) {
+ return {
+ statusCode: 404,
+ body: 'Not found'
+ };
+ }
+
+ const response = await app.render(request);
+ const body = await response.text();
+
+ return {
+ statusCode: 200,
+ headers: Object.fromEntries(response.headers.entries()),
+ body
+ };
+ }
+
+ return { handler };
+};
diff --git a/packages/integrations/netlify/tsconfig.json b/packages/integrations/netlify/tsconfig.json
new file mode 100644
index 000000000..44baf375c
--- /dev/null
+++ b/packages/integrations/netlify/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "include": ["src"],
+ "compilerOptions": {
+ "allowJs": true,
+ "module": "ES2020",
+ "outDir": "./dist",
+ "target": "ES2020"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c0da432e9..20e1d39d9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1177,6 +1177,19 @@ importers:
astro: link:../../astro
astro-scripts: link:../../../scripts
+ packages/integrations/netlify:
+ specifiers:
+ '@astrojs/webapi': ^0.11.0
+ '@netlify/functions': ^1.0.0
+ astro: workspace:*
+ astro-scripts: workspace:*
+ dependencies:
+ '@astrojs/webapi': link:../../webapi
+ devDependencies:
+ '@netlify/functions': 1.0.0
+ astro: link:../../astro
+ astro-scripts: link:../../../scripts
+
packages/integrations/node:
specifiers:
'@astrojs/webapi': ^0.11.0
@@ -3413,6 +3426,13 @@ packages:
vue: 3.2.31
dev: false
+ /@netlify/functions/1.0.0:
+ resolution: {integrity: sha512-7fnJv3vr8uyyyOYPChwoec6MjzsCw1CoRUO2DhQ1BD6bOyJRlD4DUaOOGlMILB2LCT8P24p5LexEGx8AJb7xdA==}
+ engines: {node: '>=8.3.0'}
+ dependencies:
+ is-promise: 4.0.0
+ dev: true
+
/@nodelib/fs.scandir/2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -7002,6 +7022,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /is-promise/4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+ dev: true
+
/is-regex/1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'}