Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@astrojs/node

Package Overview
Dependencies
Maintainers
4
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@astrojs/node - npm Package Compare versions

Comparing version 0.0.0-imgcache-20220929145446 to 0.0.0-node-standalone-20221011210529

dist/http-server.d.ts

122

CHANGELOG.md
# @astrojs/node
## 0.0.0-imgcache-20220929145446
## 0.0.0-node-standalone-20221011210529
### Major Changes
- [#5056](https://github.com/withastro/astro/pull/5056) [`69e32cbba`](https://github.com/withastro/astro/commit/69e32cbba2ee8537a002755c34598dab834898c9) Thanks [@matthewp](https://github.com/matthewp)! - # Standalone mode for the Node.js adapter
New in `@astrojs/node` is support for **standalone mode**. With standalone mode you can start your production server without needing to write any server JavaScript yourself. The server starts simply by running the script like so:
```shell
node ./dist/server/entry.mjs
```
To enable standalone mode set the new `mode` to `'standalone'` option in your Astro config:
```js
import { defineConfig } from 'astro/config';
import nodejs from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: nodejs({
mode: 'standalone',
}),
});
```
See the @astrojs/node documentation to learn all of the options available in standalone mode.
## Breaking change
This is a semver major change because the new `mode` option is required. Existing @astrojs/node users who are using their own HTTP server framework such as Express can upgrade by setting the `mode` option to `'middleware'` which builds to a middleware mode, which is the same behavior and API as before.
```js
import { defineConfig } from 'astro/config';
import nodejs from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: nodejs({
mode: 'middleware',
}),
});
```
### Minor Changes
- [#5056](https://github.com/withastro/astro/pull/5056) [`69e32cbba`](https://github.com/withastro/astro/commit/69e32cbba2ee8537a002755c34598dab834898c9) Thanks [@matthewp](https://github.com/matthewp)! - # Adapter support for `astro preview`
Adapters are now about to support the `astro preview` command via a new integration option. The Node.js adapter `@astrojs/node` is the first of the built-in adapters to gain support for this. What this means is that if you are using `@astrojs/node` you can new preview your SSR app by running:
```shell
npm run preview
```
## Adapter API
We will be updating the other first party Astro adapters to support preview over time. Adapters can opt-in to this feature by providing the `previewEntrypoint` via the `setAdapter` function in `astro:config:done` hook. The Node.js adapter's code looks like this:
```diff
export default function() {
return {
name: '@astrojs/node',
hooks: {
'astro:config:done': ({ setAdapter, config }) => {
setAdapter({
name: '@astrojs/node',
serverEntrypoint: '@astrojs/node/server.js',
+ previewEntrypoint: '@astrojs/node/preview.js',
exports: ['handler'],
});
// more here
}
}
};
}
```
The `previewEntrypoint` is a module in the adapter's package that is a Node.js script. This script is run when `astro preview` is run and is charged with starting up the built server. See the Node.js implementation in `@astrojs/node` to see how that is implemented.
- [#5056](https://github.com/withastro/astro/pull/5056) [`69e32cbba`](https://github.com/withastro/astro/commit/69e32cbba2ee8537a002755c34598dab834898c9) Thanks [@matthewp](https://github.com/matthewp)! - # New build configuration
The ability to customize SSR build configuration more granular is now available in Astro. You can now customize the output folder for `server` (the server code for SSR), `client` (your client-side JavaScript and assets), and `serverEntry` (the name of the entrypoint server module). Here are the defaults:
```js
import { defineConfig } from 'astro/config';
export default defineConfig({
output: 'server',
build: {
server: './dist/server/',
client: './dist/client/',
serverEntry: 'entry.mjs',
},
});
```
These new configuration options are only supported in SSR mode and are ignored when building to SSG (a static site).
## Integration hook change
The integration hook `astro:build:start` includes a param `buildConfig` which includes all of these same options. You can continue to use this param in Astro 1.x, but it is deprecated in favor of the new `build.config` options. All if the built-in adapters have been updated to the new format. If you have an integration that depends on this param we suggest upgrading to do this instead:
```js
export default function myIntegration() {
return {
name: 'my-integration',
hooks: {
'astro:config:setup': ({ updateConfig }) => {
updateConfig({
build: {
server: '...',
},
});
},
},
};
}
```
## 1.1.0
### Minor Changes
- [#4876](https://github.com/withastro/astro/pull/4876) [`d3091f89e`](https://github.com/withastro/astro/commit/d3091f89e92fcfe1ad48daca74055d54b1c853a3) Thanks [@matthewp](https://github.com/matthewp)! - Adds the Astro.cookies API

@@ -8,0 +128,0 @@

5

dist/index.d.ts
import type { AstroAdapter, AstroIntegration } from 'astro';
export declare function getAdapter(): AstroAdapter;
export default function createIntegration(): AstroIntegration;
import type { Options, UserOptions } from './types';
export declare function getAdapter(options: Options): AstroAdapter;
export default function createIntegration(userOptions: UserOptions): AstroIntegration;

@@ -1,9 +0,16 @@

function getAdapter() {
function getAdapter(options) {
return {
name: "@astrojs/node",
serverEntrypoint: "@astrojs/node/server.js",
exports: ["handler"]
previewEntrypoint: "@astrojs/node/preview.js",
exports: ["handler"],
args: options
};
}
function createIntegration() {
function createIntegration(userOptions) {
if (!(userOptions == null ? void 0 : userOptions.mode)) {
throw new Error(`[@astrojs/node] Setting the 'mode' option is required.`);
}
let needsBuildConfig = false;
let _options;
return {

@@ -13,6 +20,21 @@ name: "@astrojs/node",

"astro:config:done": ({ setAdapter, config }) => {
setAdapter(getAdapter());
var _a, _b, _c;
needsBuildConfig = !((_a = config.build) == null ? void 0 : _a.server);
_options = {
...userOptions,
client: (_b = config.build.client) == null ? void 0 : _b.toString(),
server: (_c = config.build.server) == null ? void 0 : _c.toString(),
host: config.server.host,
port: config.server.port
};
setAdapter(getAdapter(_options));
if (config.output === "static") {
console.warn(`[@astrojs/node] \`output: "server"\` is required to use this adapter.`);
}
},
"astro:build:start": ({ buildConfig }) => {
if (needsBuildConfig) {
_options.client = buildConfig.client.toString();
_options.server = buildConfig.server.toString();
}
}

@@ -19,0 +41,0 @@ }

@@ -0,5 +1,7 @@

/// <reference types="node" />
import type { SSRManifest } from 'astro';
import type { IncomingMessage, ServerResponse } from 'http';
import type { Options } from './types';
export declare function createExports(manifest: SSRManifest): {
handler(req: IncomingMessage, res: ServerResponse, next?: ((err?: unknown) => void) | undefined): Promise<void>;
handler: (req: import("http").IncomingMessage, res: import("http").ServerResponse<import("http").IncomingMessage>, next?: ((err?: unknown) => void) | undefined) => Promise<void>;
};
export declare function start(manifest: SSRManifest, options: Options): void;
import { polyfill } from "@astrojs/webapi";
import { NodeApp } from "astro/app/node";
import middleware from "./middleware.js";
import startServer from "./standalone.js";
polyfill(globalThis, {

@@ -9,46 +11,15 @@ exclude: "window document"

return {
async handler(req, res, next) {
try {
const route = app.match(req);
if (route) {
try {
const response = await app.render(req);
await writeWebResponse(app, res, response);
} catch (err) {
if (next) {
next(err);
} else {
throw err;
}
}
} else if (next) {
return next();
}
} catch (err) {
if (!res.headersSent) {
res.writeHead(500, `Server error`);
res.end();
}
}
}
handler: middleware(app)
};
}
async function writeWebResponse(app, res, webResponse) {
const { status, headers, body } = webResponse;
if (app.setCookieHeaders) {
const setCookieHeaders = Array.from(app.setCookieHeaders(webResponse));
if (setCookieHeaders.length) {
res.setHeader("Set-Cookie", setCookieHeaders);
}
function start(manifest, options) {
if (options.mode !== "standalone" || process.env.ASTRO_NODE_AUTOSTART === "disabled") {
return;
}
res.writeHead(status, Object.fromEntries(headers.entries()));
if (body) {
for await (const chunk of body) {
res.write(chunk);
}
}
res.end();
const app = new NodeApp(manifest);
startServer(app, options);
}
export {
createExports
createExports,
start
};
{
"name": "@astrojs/node",
"description": "Deploy your site to a Node.js server",
"version": "0.0.0-imgcache-20220929145446",
"version": "0.0.0-node-standalone-20221011210529",
"type": "module",

@@ -23,9 +23,12 @@ "types": "./dist/index.d.ts",

"./server.js": "./dist/server.js",
"./preview.js": "./dist/preview.js",
"./package.json": "./package.json"
},
"dependencies": {
"@astrojs/webapi": "^1.1.0"
"@astrojs/webapi": "^1.1.0",
"send": "^0.18.0"
},
"devDependencies": {
"astro": "0.0.0-imgcache-20220929145446",
"@types/send": "^0.17.1",
"astro": "0.0.0-node-standalone-20221011210529",
"astro-scripts": "0.0.8",

@@ -32,0 +35,0 @@ "chai": "^4.3.6",

@@ -1,2 +0,2 @@

# @astrojs/node 🔲
# @astrojs/node

@@ -14,3 +14,3 @@ This adapter allows Astro to deploy your SSR site to Node targets.

## Why Astro Node
## Why @astrojs/node

@@ -21,3 +21,3 @@ If you're using Astro as a static site builder—its behavior out of the box—you don't need an adapter.

[Node](https://nodejs.org/en/) is a JavaScript runtime for server-side code. Frameworks like [Express](https://expressjs.com/) are built on top of it and make it easier to write server applications in Node. This adapter provides access to Node's API and creates a script to run your Astro project that can be utilized in Node applications.
[Node.js](https://nodejs.org/en/) is a JavaScript runtime for server-side code. @astrojs/node can be used either in standalone mode or as middleware for other http servers, such as [Express](https://expressjs.com/).

@@ -47,3 +47,3 @@ ## Installation

```js title="astro.config.mjs" ins={2, 5-6}
```js title="astro.config.mjs" ins={2, 5-8}
import { defineConfig } from 'astro/config';

@@ -54,13 +54,39 @@ import node from '@astrojs/node';

output: 'server',
adapter: node(),
adapter: node({
mode: 'standalone'
}),
});
```
## Configuration
This adapter does not expose any configuration options.
@astrojs/node can be configured by passing options into the adapter function. The following options are available:
### Mode
Controls whether the adapter builds to `middleware` or `standalone` mode.
- `middleware` mode allows the built output to be used as middleware for another Node.js server, like Express.js or Fastify.
```js
import { defineConfig } from 'astro/config';
import nodejs from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'middleware'
}),
});
```
- `standalone` mode builds to server that automatically starts with the entry module is run. This allows you to more easily deploy your build to a host without any additional code.
## Usage
After [performing a build](https://docs.astro.build/en/guides/deploy/#building-your-site-locally) there will be a `dist/server/entry.mjs` module that exposes a `handler` function. This works like a [middleware](https://expressjs.com/en/guide/using-middleware.html) function: it can handle incoming requests and respond accordingly.
First, [performing a build](https://docs.astro.build/en/guides/deploy/#building-your-site-locally). Depending on which `mode` selected (see above) follow the appropriate steps below:
### Middleware
### Using a middleware framework
You can use this `handler` with any framework that supports the Node `request` and `response` objects.
The server entrypoint is built to `./dist/server/entry.mjs` by default. This module exports a `handler` function that can be used with any framework that supports the Node `request` and `response` objects.

@@ -80,41 +106,48 @@ For example, with Express:

Note that middleware mode does not do file servering. You'll need to configure your HTTP framework to do that for you. By default the client assets are written to `./dist/client/`.
### Using `http`
### Standalone
This output script does not require you use Express and can work with even the built-in `http` and `https` node modules. The handler does follow the convention calling an error function when either
In standalone mode a server starts when the server entrypoint is run. By default it is built to `./dist/server/entry.mjs`. You can run it with:
- A route is not found for the request.
- There was an error rendering.
```shell
node ./dist/server/entry.mjs
```
You can use these to implement your own 404 behavior like so:
For standalone mode the server handles file servering in addition to the page and API routes.
```js
import http from 'http';
import { handler as ssrHandler } from './dist/server/entry.mjs';
#### HTTPS
http.createServer(function(req, res) {
ssrHandler(req, res, err => {
if(err) {
res.writeHead(500);
res.end(err.toString());
} else {
// Serve your static assets here maybe?
// 404?
res.writeHead(404);
res.end();
}
});
}).listen(8080);
By default the standalone server uses HTTP. This works well if you have a proxy server in front of it that does HTTPS. If you need the standalone server to run HTTPS itself you need to provide your SSL key and certificate.
You can pass the path to your key and certification via the environment variables `SERVER_CERT_PATH` and `SERVER_KEY_PATH`. This is how you might pass them in bash:
```bash
SERVER_KEY_PATH=./private/key.pem SERVER_CERT_PATH=./private/cert.pem node ./dist/server/entry.mjs
```
## Troubleshooting
### SyntaxError: Named export 'compile' not found
## Configuration
You may see this when running the entry script if it was built with npm or Yarn. This is a [known issue](https://github.com/withastro/astro/issues/4974) that will be fixed in a future release. As a workaround, add `"path-to-regexp"` to the `noExternal` array:
This adapter does not expose any configuration options.
```js title="astro.config.mjs" ins={8-12}
import { defineConfig } from 'astro/config';
## Troubleshooting
import node from "@astrojs/node";
For help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help!
export default defineConfig({
output: "server",
adapter: node(),
vite: {
ssr: {
noExternal: ["path-to-regexp"]
}
}
});
```
For more help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help!
You can also check our [Astro Integration Documentation][astro-integration] for more on integrations.

@@ -121,0 +154,0 @@

import type { AstroAdapter, AstroIntegration } from 'astro';
import type { Options, UserOptions } from './types';
export function getAdapter(): AstroAdapter {
export function getAdapter(options: Options): AstroAdapter {
return {
name: '@astrojs/node',
serverEntrypoint: '@astrojs/node/server.js',
previewEntrypoint: '@astrojs/node/preview.js',
exports: ['handler'],
args: options
};
}
export default function createIntegration(): AstroIntegration {
export default function createIntegration(userOptions: UserOptions): AstroIntegration {
if(!userOptions?.mode) {
throw new Error(`[@astrojs/node] Setting the 'mode' option is required.`)
}
let needsBuildConfig = false;
let _options: Options;
return {

@@ -16,3 +25,11 @@ name: '@astrojs/node',

'astro:config:done': ({ setAdapter, config }) => {
setAdapter(getAdapter());
needsBuildConfig = !config.build?.server;
_options = {
...userOptions,
client: config.build.client?.toString(),
server: config.build.server?.toString(),
host: config.server.host,
port: config.server.port,
};
setAdapter(getAdapter(_options));

@@ -23,4 +40,11 @@ if (config.output === 'static') {

},
'astro:build:start': ({ buildConfig }) => {
// Backwards compat
if(needsBuildConfig) {
_options.client = buildConfig.client.toString();
_options.server = buildConfig.server.toString();
}
}
},
};
}

@@ -0,6 +1,7 @@

import type { SSRManifest } from 'astro';
import type { Options } from './types';
import { polyfill } from '@astrojs/webapi';
import type { SSRManifest } from 'astro';
import { NodeApp } from 'astro/app/node';
import type { IncomingMessage, ServerResponse } from 'http';
import type { Readable } from 'stream';
import middleware from './middleware.js';
import startServer from './standalone.js';

@@ -14,47 +15,13 @@ polyfill(globalThis, {

return {
async handler(req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) {
try {
const route = app.match(req);
if (route) {
try {
const response = await app.render(req);
await writeWebResponse(app, res, response);
} catch (err: unknown) {
if (next) {
next(err);
} else {
throw err;
}
}
} else if (next) {
return next();
}
} catch (err: unknown) {
if (!res.headersSent) {
res.writeHead(500, `Server error`);
res.end();
}
}
},
handler: middleware(app)
};
}
async function writeWebResponse(app: NodeApp, res: ServerResponse, webResponse: Response) {
const { status, headers, body } = webResponse;
if (app.setCookieHeaders) {
const setCookieHeaders: Array<string> = Array.from(app.setCookieHeaders(webResponse));
if (setCookieHeaders.length) {
res.setHeader('Set-Cookie', setCookieHeaders);
}
export function start(manifest: SSRManifest, options: Options) {
if(options.mode !== 'standalone' || process.env.ASTRO_NODE_AUTOSTART === 'disabled') {
return;
}
res.writeHead(status, Object.fromEntries(headers.entries()));
if (body) {
for await (const chunk of body as unknown as Readable) {
res.write(chunk);
}
}
res.end();
const app = new NodeApp(manifest);
startServer(app, options);
}

@@ -13,3 +13,3 @@ import nodejs from '../dist/index.js';

output: 'server',
adapter: nodejs(),
adapter: nodejs({ mode: 'middleware' }),
});

@@ -16,0 +16,0 @@ await fixture.build();

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc