@vigla/adapter-node 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,13 @@
1
+ import type { Builder } from '@vigla/kit';
2
+ export interface Asset {
3
+ url: string;
4
+ file: string;
5
+ directory: 'client' | 'prerendered';
6
+ etag: string;
7
+ br: boolean;
8
+ gz: boolean;
9
+ aliases: string[];
10
+ canonical?: string;
11
+ }
12
+ export declare function collectAssets(builder: Builder, client: string, prerendered: string, files: string[], pages: string[], compressed: boolean): Promise<Asset[]>;
13
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,KAAK;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,QAAQ,GAAG,aAAa,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,KAAK,EAAE,CAAC,CAoDlB"}
package/dist/assets.js ADDED
@@ -0,0 +1,49 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createReadStream, existsSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ export async function collectAssets(builder, client, prerendered, files, pages, compressed) {
5
+ const base = builder.config.paths.base;
6
+ const assets = [];
7
+ const record = async (directory, root, file, url, aliases = [], canonical) => {
8
+ const hash = createHash('sha256');
9
+ for await (const chunk of createReadStream(path.join(root, file)))
10
+ hash.update(chunk);
11
+ assets.push({
12
+ directory,
13
+ file,
14
+ url,
15
+ aliases,
16
+ canonical,
17
+ etag: hash.digest('base64url'),
18
+ br: compressed && existsSync(path.join(root, file + '.br')),
19
+ gz: compressed && existsSync(path.join(root, file + '.gz'))
20
+ });
21
+ };
22
+ for (const file of [...files].sort()) {
23
+ if (file
24
+ .split('/')
25
+ .some((part, i) => part.startsWith('.') && !(i === 0 && part === '.well-known')))
26
+ continue;
27
+ const url = `${base}/${file}`;
28
+ let aliases = [];
29
+ if (file.endsWith('.html')) {
30
+ const slash = file.endsWith('/index.html') || file === 'index.html'
31
+ ? url.slice(0, -10)
32
+ : url.slice(0, -5) + '/';
33
+ aliases = slash === '/' ? ['/'] : [slash, slash.slice(0, -1)];
34
+ }
35
+ await record('client', client, file, url, aliases);
36
+ }
37
+ for (const url of builder.prerendered.paths) {
38
+ const page = builder.prerendered.pages.get(url);
39
+ const stripped = url.slice(base.length + 1);
40
+ const candidates = page
41
+ ? [page.file]
42
+ : [stripped || 'index.html', stripped + (stripped.endsWith('/') ? 'index.html' : '.html')];
43
+ const file = candidates.find((candidate) => pages.includes(candidate));
44
+ if (file)
45
+ await record('prerendered', prerendered, file, url, [], url);
46
+ }
47
+ return assets;
48
+ }
49
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare class Environment {
2
+ readonly values: Record<string, string | undefined>;
3
+ readonly prefix: string;
4
+ constructor(values: Record<string, string | undefined>, prefix?: string);
5
+ get(name: string, fallback?: string): string | undefined;
6
+ integer(name: string, fallback?: number): number | undefined;
7
+ bytes(name: string, fallback: string): number;
8
+ }
9
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAW;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,MAAM,SAAK,EA0BlE;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGvD;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3D;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ5C;CACD"}
package/dist/env.js ADDED
@@ -0,0 +1,52 @@
1
+ export class Environment {
2
+ values;
3
+ prefix;
4
+ constructor(values, prefix = '') {
5
+ this.values = values;
6
+ this.prefix = prefix;
7
+ const names = new Set([
8
+ 'ORIGIN',
9
+ 'SOCKET_PATH',
10
+ 'HOST',
11
+ 'PORT',
12
+ 'XFF_DEPTH',
13
+ 'ADDRESS_HEADER',
14
+ 'PROTOCOL_HEADER',
15
+ 'HOST_HEADER',
16
+ 'PORT_HEADER',
17
+ 'BODY_SIZE_LIMIT',
18
+ 'SHUTDOWN_TIMEOUT',
19
+ 'IDLE_TIMEOUT',
20
+ 'KEEP_ALIVE_TIMEOUT',
21
+ 'HEADERS_TIMEOUT'
22
+ ]);
23
+ if (prefix)
24
+ for (const key of Object.keys(values)) {
25
+ if (key.startsWith(prefix) && !names.has(key.slice(prefix.length)))
26
+ throw new Error(`Unexpected environment variable ${key}; change envPrefix to avoid conflicts`);
27
+ }
28
+ }
29
+ get(name, fallback) {
30
+ const key = name === 'LISTEN_PID' || name === 'LISTEN_FDS' ? name : this.prefix + name;
31
+ return this.values[key] ?? fallback;
32
+ }
33
+ integer(name, fallback) {
34
+ const value = this.get(name);
35
+ if (value === undefined || value === '')
36
+ return fallback;
37
+ const number = Number(value);
38
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(number))
39
+ throw new Error(`Invalid ${this.prefix + name}: expected a non-negative integer`);
40
+ return number;
41
+ }
42
+ bytes(name, fallback) {
43
+ const value = this.get(name, fallback);
44
+ const units = { K: 1024, M: 1024 ** 2, G: 1024 ** 3 };
45
+ const multiplier = units[value.slice(-1).toUpperCase()] ?? 1;
46
+ const bytes = Number(multiplier === 1 ? value : value.slice(0, -1)) * multiplier;
47
+ if (Number.isNaN(bytes) || bytes < 0)
48
+ throw new Error(`Invalid ${this.prefix + name}: expected a byte size`);
49
+ return bytes;
50
+ }
51
+ }
52
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAW;IACd,MAAM,CAAqC;IAC3C,MAAM,CAAS;IAExB,YAAY,MAA0C,EAAE,MAAM,GAAG,EAAE;QAClE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC;YACrB,QAAQ;YACR,aAAa;YACb,MAAM;YACN,MAAM;YACN,WAAW;YACX,gBAAgB;YAChB,iBAAiB;YACjB,aAAa;YACb,aAAa;YACb,iBAAiB;YACjB,kBAAkB;YAClB,cAAc;YACd,oBAAoB;YACpB,iBAAiB;SACjB,CAAC,CAAC;QACH,IAAI,MAAM;YACT,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBACjE,MAAM,IAAI,KAAK,CACd,mCAAmC,GAAG,uCAAuC,CAC7E,CAAC;YACJ,CAAC;IACH,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,QAAiB;QAClC,MAAM,GAAG,GAAG,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACvF,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,QAAiB;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,QAAQ,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,MAAM,GAAG,IAAI,mCAAmC,CAAC,CAAC;QACnF,OAAO,MAAM,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAY,EAAE,QAAgB;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAE,CAAC;QACxC,MAAM,KAAK,GAA2B,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QAC9E,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;QACjF,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAwB,CAAC,CAAC;QACxE,OAAO,KAAK,CAAC;IACd,CAAC;CACD"}
@@ -0,0 +1,15 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { Server } from '@vigla/kit';
3
+ import type { Asset } from './assets.ts';
4
+ import { Environment } from './env.ts';
5
+ export type Handler = (request: IncomingMessage, response: ServerResponse, next?: () => void) => Promise<void>;
6
+ export interface Deployment {
7
+ directory: string;
8
+ base: string;
9
+ appPath: string;
10
+ origin?: string;
11
+ mimeTypes: Record<string, string>;
12
+ assets: Asset[];
13
+ }
14
+ export declare function createHandler(server: Server, deployment: Deployment, env: Environment): Promise<Handler>;
15
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAIvC,MAAM,MAAM,OAAO,GAAG,CACrB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,EACxB,IAAI,CAAC,EAAE,MAAM,IAAI,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,KAAK,EAAE,CAAC;CAChB;AAED,wBAAsB,aAAa,CAClC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,WAAW,GACd,OAAO,CAAC,OAAO,CAAC,CAwGlB"}
@@ -0,0 +1,130 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import path from 'node:path';
3
+ import { createReadableStream, getRequest, setResponse } from '@vigla/kit/node';
4
+ import { serveFile } from '@vigla/kit/internal/node';
5
+ import { Environment } from './env.js';
6
+ const scope = new AsyncLocalStorage();
7
+ export async function createHandler(server, deployment, env) {
8
+ const origin = env.get('ORIGIN', deployment.origin);
9
+ const addressHeader = env.get('ADDRESS_HEADER', '').toLowerCase();
10
+ const protocolHeader = env.get('PROTOCOL_HEADER', '').toLowerCase();
11
+ const hostHeader = env.get('HOST_HEADER', '').toLowerCase();
12
+ const portHeader = env.get('PORT_HEADER', '').toLowerCase();
13
+ const depth = env.integer('XFF_DEPTH', 1);
14
+ const limit = env.bytes('BODY_SIZE_LIMIT', '512K');
15
+ const read = (file) => createReadableStream(path.join(deployment.directory, 'client' + deployment.base, file));
16
+ await server.init({ env: env.values, read, scope });
17
+ const files = new Map();
18
+ for (const asset of deployment.assets)
19
+ if (!files.has(asset.url))
20
+ files.set(asset.url, asset);
21
+ for (const asset of deployment.assets)
22
+ for (const alias of asset.aliases)
23
+ if (!files.has(alias))
24
+ files.set(alias, asset);
25
+ for (const asset of deployment.assets)
26
+ if (asset.canonical) {
27
+ const alternate = asset.canonical.endsWith('/')
28
+ ? asset.canonical.slice(0, -1)
29
+ : asset.canonical + '/';
30
+ if (alternate && !files.has(alternate))
31
+ files.set(alternate, asset.canonical);
32
+ }
33
+ return async (request, response) => {
34
+ const raw = request.url ?? '/';
35
+ const query = raw.indexOf('?');
36
+ let pathname = query < 0 ? raw : raw.slice(0, query);
37
+ const search = query < 0 ? '' : raw.slice(query);
38
+ try {
39
+ pathname = pathname.split('%25').map(decodeURI).join('%25');
40
+ }
41
+ catch { }
42
+ const asset = files.get(pathname);
43
+ if (asset) {
44
+ if (request.method !== 'GET' && request.method !== 'HEAD') {
45
+ response.writeHead(405, { allow: 'GET, HEAD' }).end();
46
+ return;
47
+ }
48
+ if (typeof asset === 'string') {
49
+ const segment = asset.replace(/\/$/, '').split('/').at(-1);
50
+ const location = pathname.endsWith('/') ? `../${segment}` : `./${segment}/`;
51
+ response.writeHead(308, { location: encodeURI(location) + search }).end();
52
+ return;
53
+ }
54
+ const variant = encoding(request.headers['accept-encoding'], asset);
55
+ if (serveFile({
56
+ directory: path.join(deployment.directory, asset.directory + deployment.base),
57
+ pathname,
58
+ request,
59
+ response,
60
+ representation: {
61
+ file: asset.file + (variant ? '.' + variant : ''),
62
+ etag: `"${asset.etag}${variant ? '.' + variant : ''}"`,
63
+ type: deployment.mimeTypes[path.extname(asset.file)],
64
+ cacheControl: asset.url.startsWith(`/${deployment.appPath}/immutable/`)
65
+ ? 'public,max-age=31536000,immutable'
66
+ : undefined,
67
+ encoding: variant === 'gz' ? 'gzip' : variant,
68
+ vary: asset.br || asset.gz ? 'Accept-Encoding' : undefined
69
+ }
70
+ }))
71
+ return;
72
+ }
73
+ let web;
74
+ try {
75
+ const header = (name) => {
76
+ const value = name ? request.headers[name] : undefined;
77
+ if (Array.isArray(value) && value.length > 1)
78
+ throw new Error(`Multiple ${name} headers`);
79
+ return Array.isArray(value) ? value[0] : value;
80
+ };
81
+ let base = origin;
82
+ if (!base) {
83
+ const protocol = decodeURIComponent(header(protocolHeader) || 'https');
84
+ const host = header(hostHeader) || header('host');
85
+ const port = header(portHeader);
86
+ if (!/^https?$/i.test(protocol) || !host || (port && !/^\d+$/.test(port)))
87
+ throw new Error('Invalid request origin');
88
+ base = new URL(`${protocol}://${host}${port ? ':' + port : ''}`).origin;
89
+ }
90
+ web = getRequest({ base, request, response, bodySizeLimit: limit });
91
+ }
92
+ catch {
93
+ response.writeHead(400).end('Bad Request');
94
+ return;
95
+ }
96
+ const result = await server.respond(web, {
97
+ read,
98
+ platform: { req: request },
99
+ getClientAddress: () => {
100
+ if (!addressHeader)
101
+ return request.socket.remoteAddress;
102
+ const value = request.headers[addressHeader];
103
+ if (value === undefined)
104
+ throw new Error(`Missing ${addressHeader} specified by ${env.prefix}ADDRESS_HEADER`);
105
+ const text = Array.isArray(value) ? value.join(',') : value;
106
+ if (addressHeader !== 'x-forwarded-for')
107
+ return text;
108
+ const addresses = text.split(',');
109
+ if (depth < 1 || depth > addresses.length)
110
+ throw new Error(`Invalid ${env.prefix}XFF_DEPTH for ${addresses.length} addresses`);
111
+ return addresses[addresses.length - depth].trim();
112
+ }
113
+ });
114
+ if (result.headers.get('content-type')?.startsWith('text/event-stream'))
115
+ result.headers.set('x-accel-buffering', 'no');
116
+ setResponse(response, result);
117
+ };
118
+ }
119
+ function encoding(header, asset) {
120
+ const weights = new Map();
121
+ for (const part of header?.toLowerCase().split(',') ?? []) {
122
+ const [name = '', ...params] = part.split(';');
123
+ const q = params.find((param) => param.trim().startsWith('q='));
124
+ weights.set(name.trim(), q ? Number(q.trim().slice(2)) || 0 : 1);
125
+ }
126
+ const br = asset.br ? (weights.get('br') ?? weights.get('*') ?? 0) : 0;
127
+ const gz = asset.gz ? (weights.get('gzip') ?? weights.get('*') ?? 0) : 0;
128
+ return gz > br ? 'gz' : br > 0 ? 'br' : undefined;
129
+ }
130
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Adapter } from '@vigla/kit';
2
+ export interface Options {
3
+ out?: string;
4
+ precompress?: boolean;
5
+ envPrefix?: string;
6
+ }
7
+ export default function adapter(options?: Options): Adapter;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAW,MAAM,YAAY,CAAC;AAGnD,MAAM,WAAW,OAAO;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,OAAO,GAAE,OAAY,GAAG,OAAO,CAkE9D"}
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { rolldown } from 'rolldown';
5
+ import { collectAssets } from './assets.js';
6
+ export default function adapter(options = {}) {
7
+ const { out = 'build', precompress = true, envPrefix = '' } = options;
8
+ return {
9
+ name: '@vigla/adapter-node',
10
+ supports: { read: () => true, instrumentation: () => true },
11
+ async adapt(builder) {
12
+ builder.rimraf(out);
13
+ mkdirSync(out, { recursive: true });
14
+ const base = builder.config.paths.base;
15
+ const client = path.join(out, 'client' + base);
16
+ const prerendered = path.join(out, 'prerendered' + base);
17
+ const files = builder.writeClient(client);
18
+ const pages = builder.writePrerendered(prerendered);
19
+ if (precompress)
20
+ await Promise.all([builder.compress(client), builder.compress(prerendered)]);
21
+ const assets = await collectAssets(builder, client, prerendered, files, pages, precompress);
22
+ builder.writeServer(path.join(out, 'server'));
23
+ builder.generateServerInstance(path.join(out, 'server/server.js'), {
24
+ serverDirectory: path.join(out, 'server')
25
+ });
26
+ const bundle = await rolldown({
27
+ input: fileURLToPath(new URL(`./runtime${path.extname(import.meta.url)}`, import.meta.url)),
28
+ platform: 'node',
29
+ external: [/^node:/]
30
+ });
31
+ try {
32
+ await bundle.write({ file: path.join(out, 'runtime.js'), format: 'esm' });
33
+ }
34
+ finally {
35
+ await bundle.close();
36
+ }
37
+ writeFileSync(path.join(out, 'package.json'), JSON.stringify({ type: 'module' }));
38
+ writeFileSync(path.join(out, 'deployment.json'), JSON.stringify({
39
+ base,
40
+ envPrefix,
41
+ origin: builder.config.paths.origin,
42
+ appPath: builder.getAppPath(),
43
+ mimeTypes: builder.mimeTypes,
44
+ assets
45
+ }));
46
+ writeFileSync(path.join(out, 'env.js'), `import data from './deployment.json' with { type: 'json' };\nimport { Environment } from './runtime.js';\nexport const env = new Environment(process.env, data.envPrefix);\n`);
47
+ writeFileSync(path.join(out, 'handler.js'), `import { fileURLToPath } from 'node:url';\nimport data from './deployment.json' with { type: 'json' };\nimport { server } from './server/server.js';\nimport { createHandler } from './runtime.js';\nimport { env } from './env.js';\nexport const handler = await createHandler(server, { ...data, directory: fileURLToPath(new URL('.', import.meta.url)) }, env);\n`);
48
+ writeFileSync(path.join(out, 'index.js'), `import { listen } from './runtime.js';\nimport { handler } from './handler.js';\nimport { env } from './env.js';\nexport const path = env.get('SOCKET_PATH');\nexport const host = env.get('HOST', '0.0.0.0');\nexport const port = env.get('PORT', '3000');\nexport const server = listen(handler, env, ${JSON.stringify(`${builder.identity.name}:shutdown`)});\n`);
49
+ if (builder.hasServerInstrumentationFile()) {
50
+ builder.instrument({
51
+ entrypoint: path.join(out, 'index.js'),
52
+ instrumentation: path.join(out, 'server/instrumentation.server.js'),
53
+ initializer: builder.createInstrumentationInitializer({
54
+ outputDirectory: out,
55
+ serverDirectory: path.join(out, 'server')
56
+ }),
57
+ module: { exports: ['path', 'host', 'port', 'server'] }
58
+ });
59
+ }
60
+ }
61
+ };
62
+ }
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { Environment } from './env.ts';
2
+ export { createHandler } from './handler.ts';
3
+ export { listen } from './server.ts';
4
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { Environment } from './env.js';
2
+ export { createHandler } from './handler.js';
3
+ export { listen } from './server.js';
4
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type Server } from 'node:http';
2
+ import type { Handler } from './handler.ts';
3
+ import { Environment } from './env.ts';
4
+ export declare function listen(handler: Handler, env: Environment, shutdownEvent: string): Server;
5
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAGtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CA4ExF"}
package/dist/server.js ADDED
@@ -0,0 +1,124 @@
1
+ import { statSync, unlinkSync } from 'node:fs';
2
+ import { createServer } from 'node:http';
3
+ import { connect } from 'node:net';
4
+ import { format } from 'node:url';
5
+ import { Environment } from './env.js';
6
+ export function listen(handler, env, shutdownEvent) {
7
+ const socket = env.get('SOCKET_PATH');
8
+ const host = env.get('HOST', '0.0.0.0');
9
+ const port = env.get('PORT', '3000');
10
+ const pid = env.integer('LISTEN_PID', 0);
11
+ const fds = env.integer('LISTEN_FDS', 0);
12
+ if (pid !== 0 && pid !== process.pid)
13
+ throw new Error(`LISTEN_PID ${pid} does not match process ${process.pid}`);
14
+ if (fds > 1)
15
+ throw new Error('Socket activation accepts only one file descriptor');
16
+ const activation = pid === process.pid && fds === 1;
17
+ const shutdown = env.integer('SHUTDOWN_TIMEOUT', 30);
18
+ const idle = env.integer('IDLE_TIMEOUT', 0);
19
+ const keepAlive = env.integer('KEEP_ALIVE_TIMEOUT');
20
+ const headers = env.integer('HEADERS_TIMEOUT');
21
+ let requests = 0;
22
+ let closing = false;
23
+ let deadline;
24
+ let idleTimer;
25
+ const server = createServer((request, response) => {
26
+ requests++;
27
+ clearTimeout(idleTimer);
28
+ let completed = false;
29
+ const complete = () => {
30
+ if (completed)
31
+ return;
32
+ completed = true;
33
+ requests--;
34
+ if (closing)
35
+ server.closeIdleConnections();
36
+ else if (activation && idle && requests === 0)
37
+ idleTimer = setTimeout(() => stop('IDLE'), idle * 1000);
38
+ };
39
+ response.once('finish', complete);
40
+ response.once('close', complete);
41
+ void handler(request, response, () => response.writeHead(404).end()).catch((error) => {
42
+ console.error(error);
43
+ if (response.headersSent)
44
+ response.destroy();
45
+ else
46
+ response.writeHead(500).end('Internal Server Error');
47
+ });
48
+ });
49
+ if (keepAlive !== undefined)
50
+ server.keepAliveTimeout = keepAlive * 1000;
51
+ if (headers !== undefined)
52
+ server.headersTimeout = headers * 1000;
53
+ const stop = (reason) => {
54
+ if (closing)
55
+ return;
56
+ closing = true;
57
+ clearTimeout(idleTimer);
58
+ server.closeIdleConnections();
59
+ deadline = setTimeout(() => server.closeAllConnections(), shutdown * 1000);
60
+ server.close((error) => {
61
+ clearTimeout(deadline);
62
+ if (!error)
63
+ process.emit(shutdownEvent, reason);
64
+ });
65
+ };
66
+ const terminate = () => stop('SIGTERM');
67
+ const interrupt = () => stop('SIGINT');
68
+ process.on('SIGTERM', terminate);
69
+ process.on('SIGINT', interrupt);
70
+ server.once('close', () => {
71
+ clearTimeout(deadline);
72
+ clearTimeout(idleTimer);
73
+ process.off('SIGTERM', terminate);
74
+ process.off('SIGINT', interrupt);
75
+ });
76
+ const bind = () => server.listen(socket ? { path: socket } : { host, port: Number(port) }, () => {
77
+ const address = server.address();
78
+ const url = socket ??
79
+ (address && typeof address === 'object'
80
+ ? format({ protocol: 'http:', hostname: address.address, port: address.port })
81
+ : format({ protocol: 'http:', hostname: host, port }));
82
+ console.log(`Listening on ${url}`);
83
+ });
84
+ if (activation)
85
+ server.listen({ fd: 3 }, () => console.log('Listening on file descriptor 3'));
86
+ else if (socket)
87
+ clearStaleSocket(socket, bind);
88
+ else
89
+ bind();
90
+ return server;
91
+ }
92
+ function socketInode(path) {
93
+ try {
94
+ const stats = statSync(path);
95
+ return stats.isSocket() ? stats.ino : null;
96
+ }
97
+ catch (error) {
98
+ if (error.code !== 'ENOENT')
99
+ throw error;
100
+ return null;
101
+ }
102
+ }
103
+ function clearStaleSocket(path, then) {
104
+ const stale = socketInode(path);
105
+ if (stale === null)
106
+ return then();
107
+ const probe = connect({ path });
108
+ probe.once('connect', () => {
109
+ probe.destroy();
110
+ then();
111
+ });
112
+ probe.once('error', (error) => {
113
+ if (error.code === 'ECONNREFUSED' && socketInode(path) === stale)
114
+ try {
115
+ unlinkSync(path);
116
+ }
117
+ catch (error) {
118
+ if (error.code !== 'ENOENT')
119
+ throw error;
120
+ }
121
+ then();
122
+ });
123
+ }
124
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,17 @@
1
1
  {
2
- "name": "@vigla/adapter-node",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "@vigla/adapter-node",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "files": [
6
+ "dist",
7
+ "src"
8
+ ],
9
+ "exports": {
10
+ ".": "./dist/index.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "dependencies": {
14
+ "@vigla/kit": "0.1.0",
15
+ "rolldown": "1.2.9"
16
+ }
17
+ }
package/src/assets.ts ADDED
@@ -0,0 +1,76 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createReadStream, existsSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import type { Builder } from '@vigla/kit';
5
+
6
+ export interface Asset {
7
+ url: string;
8
+ file: string;
9
+ directory: 'client' | 'prerendered';
10
+ etag: string;
11
+ br: boolean;
12
+ gz: boolean;
13
+ aliases: string[];
14
+ canonical?: string;
15
+ }
16
+
17
+ export async function collectAssets(
18
+ builder: Builder,
19
+ client: string,
20
+ prerendered: string,
21
+ files: string[],
22
+ pages: string[],
23
+ compressed: boolean
24
+ ): Promise<Asset[]> {
25
+ const base = builder.config.paths.base;
26
+ const assets: Asset[] = [];
27
+ const record = async (
28
+ directory: Asset['directory'],
29
+ root: string,
30
+ file: string,
31
+ url: string,
32
+ aliases: string[] = [],
33
+ canonical?: string
34
+ ) => {
35
+ const hash = createHash('sha256');
36
+ for await (const chunk of createReadStream(path.join(root, file))) hash.update(chunk);
37
+ assets.push({
38
+ directory,
39
+ file,
40
+ url,
41
+ aliases,
42
+ canonical,
43
+ etag: hash.digest('base64url'),
44
+ br: compressed && existsSync(path.join(root, file + '.br')),
45
+ gz: compressed && existsSync(path.join(root, file + '.gz'))
46
+ });
47
+ };
48
+ for (const file of [...files].sort()) {
49
+ if (
50
+ file
51
+ .split('/')
52
+ .some((part, i) => part.startsWith('.') && !(i === 0 && part === '.well-known'))
53
+ )
54
+ continue;
55
+ const url = `${base}/${file}`;
56
+ let aliases: string[] = [];
57
+ if (file.endsWith('.html')) {
58
+ const slash =
59
+ file.endsWith('/index.html') || file === 'index.html'
60
+ ? url.slice(0, -10)
61
+ : url.slice(0, -5) + '/';
62
+ aliases = slash === '/' ? ['/'] : [slash, slash.slice(0, -1)];
63
+ }
64
+ await record('client', client, file, url, aliases);
65
+ }
66
+ for (const url of builder.prerendered.paths) {
67
+ const page = builder.prerendered.pages.get(url);
68
+ const stripped = url.slice(base.length + 1);
69
+ const candidates = page
70
+ ? [page.file]
71
+ : [stripped || 'index.html', stripped + (stripped.endsWith('/') ? 'index.html' : '.html')];
72
+ const file = candidates.find((candidate) => pages.includes(candidate));
73
+ if (file) await record('prerendered', prerendered, file, url, [], url);
74
+ }
75
+ return assets;
76
+ }
package/src/env.ts ADDED
@@ -0,0 +1,56 @@
1
+ export class Environment {
2
+ readonly values: Record<string, string | undefined>;
3
+ readonly prefix: string;
4
+
5
+ constructor(values: Record<string, string | undefined>, prefix = '') {
6
+ this.values = values;
7
+ this.prefix = prefix;
8
+ const names = new Set([
9
+ 'ORIGIN',
10
+ 'SOCKET_PATH',
11
+ 'HOST',
12
+ 'PORT',
13
+ 'XFF_DEPTH',
14
+ 'ADDRESS_HEADER',
15
+ 'PROTOCOL_HEADER',
16
+ 'HOST_HEADER',
17
+ 'PORT_HEADER',
18
+ 'BODY_SIZE_LIMIT',
19
+ 'SHUTDOWN_TIMEOUT',
20
+ 'IDLE_TIMEOUT',
21
+ 'KEEP_ALIVE_TIMEOUT',
22
+ 'HEADERS_TIMEOUT'
23
+ ]);
24
+ if (prefix)
25
+ for (const key of Object.keys(values)) {
26
+ if (key.startsWith(prefix) && !names.has(key.slice(prefix.length)))
27
+ throw new Error(
28
+ `Unexpected environment variable ${key}; change envPrefix to avoid conflicts`
29
+ );
30
+ }
31
+ }
32
+
33
+ get(name: string, fallback?: string): string | undefined {
34
+ const key = name === 'LISTEN_PID' || name === 'LISTEN_FDS' ? name : this.prefix + name;
35
+ return this.values[key] ?? fallback;
36
+ }
37
+
38
+ integer(name: string, fallback?: number): number | undefined {
39
+ const value = this.get(name);
40
+ if (value === undefined || value === '') return fallback;
41
+ const number = Number(value);
42
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(number))
43
+ throw new Error(`Invalid ${this.prefix + name}: expected a non-negative integer`);
44
+ return number;
45
+ }
46
+
47
+ bytes(name: string, fallback: string): number {
48
+ const value = this.get(name, fallback)!;
49
+ const units: Record<string, number> = { K: 1024, M: 1024 ** 2, G: 1024 ** 3 };
50
+ const multiplier = units[value.slice(-1).toUpperCase()] ?? 1;
51
+ const bytes = Number(multiplier === 1 ? value : value.slice(0, -1)) * multiplier;
52
+ if (Number.isNaN(bytes) || bytes < 0)
53
+ throw new Error(`Invalid ${this.prefix + name}: expected a byte size`);
54
+ return bytes;
55
+ }
56
+ }
package/src/handler.ts ADDED
@@ -0,0 +1,147 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import type { IncomingMessage, ServerResponse } from 'node:http';
3
+ import path from 'node:path';
4
+ import type { Server } from '@vigla/kit';
5
+ import { createReadableStream, getRequest, setResponse } from '@vigla/kit/node';
6
+ import { serveFile } from '@vigla/kit/internal/node';
7
+ import type { Asset } from './assets.ts';
8
+ import { Environment } from './env.ts';
9
+
10
+ const scope = new AsyncLocalStorage();
11
+
12
+ export type Handler = (
13
+ request: IncomingMessage,
14
+ response: ServerResponse,
15
+ next?: () => void
16
+ ) => Promise<void>;
17
+
18
+ export interface Deployment {
19
+ directory: string;
20
+ base: string;
21
+ appPath: string;
22
+ origin?: string;
23
+ mimeTypes: Record<string, string>;
24
+ assets: Asset[];
25
+ }
26
+
27
+ export async function createHandler(
28
+ server: Server,
29
+ deployment: Deployment,
30
+ env: Environment
31
+ ): Promise<Handler> {
32
+ const origin = env.get('ORIGIN', deployment.origin);
33
+ const addressHeader = env.get('ADDRESS_HEADER', '')!.toLowerCase();
34
+ const protocolHeader = env.get('PROTOCOL_HEADER', '')!.toLowerCase();
35
+ const hostHeader = env.get('HOST_HEADER', '')!.toLowerCase();
36
+ const portHeader = env.get('PORT_HEADER', '')!.toLowerCase();
37
+ const depth = env.integer('XFF_DEPTH', 1)!;
38
+ const limit = env.bytes('BODY_SIZE_LIMIT', '512K');
39
+ const read = (file: string) =>
40
+ createReadableStream(path.join(deployment.directory, 'client' + deployment.base, file));
41
+ await server.init({ env: env.values, read, scope });
42
+ const files = new Map<string, Asset | string>();
43
+ for (const asset of deployment.assets) if (!files.has(asset.url)) files.set(asset.url, asset);
44
+ for (const asset of deployment.assets)
45
+ for (const alias of asset.aliases) if (!files.has(alias)) files.set(alias, asset);
46
+ for (const asset of deployment.assets)
47
+ if (asset.canonical) {
48
+ const alternate = asset.canonical.endsWith('/')
49
+ ? asset.canonical.slice(0, -1)
50
+ : asset.canonical + '/';
51
+ if (alternate && !files.has(alternate)) files.set(alternate, asset.canonical);
52
+ }
53
+ return async (request, response) => {
54
+ const raw = request.url ?? '/';
55
+ const query = raw.indexOf('?');
56
+ let pathname = query < 0 ? raw : raw.slice(0, query);
57
+ const search = query < 0 ? '' : raw.slice(query);
58
+ try {
59
+ pathname = pathname.split('%25').map(decodeURI).join('%25');
60
+ } catch {}
61
+ const asset = files.get(pathname);
62
+ if (asset) {
63
+ if (request.method !== 'GET' && request.method !== 'HEAD') {
64
+ response.writeHead(405, { allow: 'GET, HEAD' }).end();
65
+ return;
66
+ }
67
+ if (typeof asset === 'string') {
68
+ const segment = asset.replace(/\/$/, '').split('/').at(-1);
69
+ const location = pathname.endsWith('/') ? `../${segment}` : `./${segment}/`;
70
+ response.writeHead(308, { location: encodeURI(location) + search }).end();
71
+ return;
72
+ }
73
+ const variant = encoding(request.headers['accept-encoding'], asset);
74
+ if (
75
+ serveFile({
76
+ directory: path.join(deployment.directory, asset.directory + deployment.base),
77
+ pathname,
78
+ request,
79
+ response,
80
+ representation: {
81
+ file: asset.file + (variant ? '.' + variant : ''),
82
+ etag: `"${asset.etag}${variant ? '.' + variant : ''}"`,
83
+ type: deployment.mimeTypes[path.extname(asset.file)],
84
+ cacheControl: asset.url.startsWith(`/${deployment.appPath}/immutable/`)
85
+ ? 'public,max-age=31536000,immutable'
86
+ : undefined,
87
+ encoding: variant === 'gz' ? 'gzip' : variant,
88
+ vary: asset.br || asset.gz ? 'Accept-Encoding' : undefined
89
+ }
90
+ })
91
+ )
92
+ return;
93
+ }
94
+ let web: Request;
95
+ try {
96
+ const header = (name: string) => {
97
+ const value = name ? request.headers[name] : undefined;
98
+ if (Array.isArray(value) && value.length > 1) throw new Error(`Multiple ${name} headers`);
99
+ return Array.isArray(value) ? value[0] : value;
100
+ };
101
+ let base = origin;
102
+ if (!base) {
103
+ const protocol = decodeURIComponent(header(protocolHeader) || 'https');
104
+ const host = header(hostHeader) || header('host');
105
+ const port = header(portHeader);
106
+ if (!/^https?$/i.test(protocol) || !host || (port && !/^\d+$/.test(port)))
107
+ throw new Error('Invalid request origin');
108
+ base = new URL(`${protocol}://${host}${port ? ':' + port : ''}`).origin;
109
+ }
110
+ web = getRequest({ base, request, response, bodySizeLimit: limit });
111
+ } catch {
112
+ response.writeHead(400).end('Bad Request');
113
+ return;
114
+ }
115
+ const result = await server.respond(web, {
116
+ read,
117
+ platform: { req: request },
118
+ getClientAddress: () => {
119
+ if (!addressHeader) return request.socket.remoteAddress!;
120
+ const value = request.headers[addressHeader];
121
+ if (value === undefined)
122
+ throw new Error(`Missing ${addressHeader} specified by ${env.prefix}ADDRESS_HEADER`);
123
+ const text = Array.isArray(value) ? value.join(',') : value;
124
+ if (addressHeader !== 'x-forwarded-for') return text;
125
+ const addresses = text.split(',');
126
+ if (depth < 1 || depth > addresses.length)
127
+ throw new Error(`Invalid ${env.prefix}XFF_DEPTH for ${addresses.length} addresses`);
128
+ return addresses[addresses.length - depth]!.trim();
129
+ }
130
+ });
131
+ if (result.headers.get('content-type')?.startsWith('text/event-stream'))
132
+ result.headers.set('x-accel-buffering', 'no');
133
+ setResponse(response, result);
134
+ };
135
+ }
136
+
137
+ function encoding(header: string | undefined, asset: Asset): 'br' | 'gz' | undefined {
138
+ const weights = new Map<string, number>();
139
+ for (const part of header?.toLowerCase().split(',') ?? []) {
140
+ const [name = '', ...params] = part.split(';');
141
+ const q = params.find((param) => param.trim().startsWith('q='));
142
+ weights.set(name.trim(), q ? Number(q.trim().slice(2)) || 0 : 1);
143
+ }
144
+ const br = asset.br ? (weights.get('br') ?? weights.get('*') ?? 0) : 0;
145
+ const gz = asset.gz ? (weights.get('gzip') ?? weights.get('*') ?? 0) : 0;
146
+ return gz > br ? 'gz' : br > 0 ? 'br' : undefined;
147
+ }
package/src/index.ts ADDED
@@ -0,0 +1,80 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { rolldown } from 'rolldown';
5
+ import type { Adapter, Builder } from '@vigla/kit';
6
+ import { collectAssets } from './assets.ts';
7
+
8
+ export interface Options {
9
+ out?: string;
10
+ precompress?: boolean;
11
+ envPrefix?: string;
12
+ }
13
+
14
+ export default function adapter(options: Options = {}): Adapter {
15
+ const { out = 'build', precompress = true, envPrefix = '' } = options;
16
+ return {
17
+ name: '@vigla/adapter-node',
18
+ supports: { read: () => true, instrumentation: () => true },
19
+ async adapt(builder: Builder) {
20
+ builder.rimraf(out);
21
+ mkdirSync(out, { recursive: true });
22
+ const base = builder.config.paths.base;
23
+ const client = path.join(out, 'client' + base);
24
+ const prerendered = path.join(out, 'prerendered' + base);
25
+ const files = builder.writeClient(client);
26
+ const pages = builder.writePrerendered(prerendered);
27
+ if (precompress) await Promise.all([builder.compress(client), builder.compress(prerendered)]);
28
+ const assets = await collectAssets(builder, client, prerendered, files, pages, precompress);
29
+ builder.writeServer(path.join(out, 'server'));
30
+ builder.generateServerInstance(path.join(out, 'server/server.js'), {
31
+ serverDirectory: path.join(out, 'server')
32
+ });
33
+ const bundle = await rolldown({
34
+ input: fileURLToPath(new URL(`./runtime${path.extname(import.meta.url)}`, import.meta.url)),
35
+ platform: 'node',
36
+ external: [/^node:/]
37
+ });
38
+ try {
39
+ await bundle.write({ file: path.join(out, 'runtime.js'), format: 'esm' });
40
+ } finally {
41
+ await bundle.close();
42
+ }
43
+ writeFileSync(path.join(out, 'package.json'), JSON.stringify({ type: 'module' }));
44
+ writeFileSync(
45
+ path.join(out, 'deployment.json'),
46
+ JSON.stringify({
47
+ base,
48
+ envPrefix,
49
+ origin: builder.config.paths.origin,
50
+ appPath: builder.getAppPath(),
51
+ mimeTypes: builder.mimeTypes,
52
+ assets
53
+ })
54
+ );
55
+ writeFileSync(
56
+ path.join(out, 'env.js'),
57
+ `import data from './deployment.json' with { type: 'json' };\nimport { Environment } from './runtime.js';\nexport const env = new Environment(process.env, data.envPrefix);\n`
58
+ );
59
+ writeFileSync(
60
+ path.join(out, 'handler.js'),
61
+ `import { fileURLToPath } from 'node:url';\nimport data from './deployment.json' with { type: 'json' };\nimport { server } from './server/server.js';\nimport { createHandler } from './runtime.js';\nimport { env } from './env.js';\nexport const handler = await createHandler(server, { ...data, directory: fileURLToPath(new URL('.', import.meta.url)) }, env);\n`
62
+ );
63
+ writeFileSync(
64
+ path.join(out, 'index.js'),
65
+ `import { listen } from './runtime.js';\nimport { handler } from './handler.js';\nimport { env } from './env.js';\nexport const path = env.get('SOCKET_PATH');\nexport const host = env.get('HOST', '0.0.0.0');\nexport const port = env.get('PORT', '3000');\nexport const server = listen(handler, env, ${JSON.stringify(`${builder.identity.name}:shutdown`)});\n`
66
+ );
67
+ if (builder.hasServerInstrumentationFile()) {
68
+ builder.instrument({
69
+ entrypoint: path.join(out, 'index.js'),
70
+ instrumentation: path.join(out, 'server/instrumentation.server.js'),
71
+ initializer: builder.createInstrumentationInitializer({
72
+ outputDirectory: out,
73
+ serverDirectory: path.join(out, 'server')
74
+ }),
75
+ module: { exports: ['path', 'host', 'port', 'server'] }
76
+ });
77
+ }
78
+ }
79
+ };
80
+ }
package/src/runtime.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { Environment } from './env.ts';
2
+ export { createHandler } from './handler.ts';
3
+ export { listen } from './server.ts';
package/src/server.ts ADDED
@@ -0,0 +1,113 @@
1
+ import { statSync, unlinkSync } from 'node:fs';
2
+ import { createServer, type Server } from 'node:http';
3
+ import { connect } from 'node:net';
4
+ import { format } from 'node:url';
5
+ import type { Handler } from './handler.ts';
6
+ import { Environment } from './env.ts';
7
+
8
+ export function listen(handler: Handler, env: Environment, shutdownEvent: string): Server {
9
+ const socket = env.get('SOCKET_PATH');
10
+ const host = env.get('HOST', '0.0.0.0')!;
11
+ const port = env.get('PORT', '3000')!;
12
+ const pid = env.integer('LISTEN_PID', 0)!;
13
+ const fds = env.integer('LISTEN_FDS', 0)!;
14
+ if (pid !== 0 && pid !== process.pid)
15
+ throw new Error(`LISTEN_PID ${pid} does not match process ${process.pid}`);
16
+ if (fds > 1) throw new Error('Socket activation accepts only one file descriptor');
17
+ const activation = pid === process.pid && fds === 1;
18
+ const shutdown = env.integer('SHUTDOWN_TIMEOUT', 30)!;
19
+ const idle = env.integer('IDLE_TIMEOUT', 0)!;
20
+ const keepAlive = env.integer('KEEP_ALIVE_TIMEOUT');
21
+ const headers = env.integer('HEADERS_TIMEOUT');
22
+ let requests = 0;
23
+ let closing = false;
24
+ let deadline: ReturnType<typeof setTimeout> | undefined;
25
+ let idleTimer: ReturnType<typeof setTimeout> | undefined;
26
+ const server = createServer((request, response) => {
27
+ requests++;
28
+ clearTimeout(idleTimer);
29
+ let completed = false;
30
+ const complete = () => {
31
+ if (completed) return;
32
+ completed = true;
33
+ requests--;
34
+ if (closing) server.closeIdleConnections();
35
+ else if (activation && idle && requests === 0)
36
+ idleTimer = setTimeout(() => stop('IDLE'), idle * 1000);
37
+ };
38
+ response.once('finish', complete);
39
+ response.once('close', complete);
40
+ void handler(request, response, () => response.writeHead(404).end()).catch((error: unknown) => {
41
+ console.error(error);
42
+ if (response.headersSent) response.destroy();
43
+ else response.writeHead(500).end('Internal Server Error');
44
+ });
45
+ });
46
+ if (keepAlive !== undefined) server.keepAliveTimeout = keepAlive * 1000;
47
+ if (headers !== undefined) server.headersTimeout = headers * 1000;
48
+ const stop = (reason: 'SIGTERM' | 'SIGINT' | 'IDLE') => {
49
+ if (closing) return;
50
+ closing = true;
51
+ clearTimeout(idleTimer);
52
+ server.closeIdleConnections();
53
+ deadline = setTimeout(() => server.closeAllConnections(), shutdown * 1000);
54
+ server.close((error) => {
55
+ clearTimeout(deadline);
56
+ if (!error)
57
+ (process.emit as (event: string, reason: string) => boolean)(shutdownEvent, reason);
58
+ });
59
+ };
60
+ const terminate = () => stop('SIGTERM');
61
+ const interrupt = () => stop('SIGINT');
62
+ process.on('SIGTERM', terminate);
63
+ process.on('SIGINT', interrupt);
64
+ server.once('close', () => {
65
+ clearTimeout(deadline);
66
+ clearTimeout(idleTimer);
67
+ process.off('SIGTERM', terminate);
68
+ process.off('SIGINT', interrupt);
69
+ });
70
+ const bind = () =>
71
+ server.listen(socket ? { path: socket } : { host, port: Number(port) }, () => {
72
+ const address = server.address();
73
+ const url =
74
+ socket ??
75
+ (address && typeof address === 'object'
76
+ ? format({ protocol: 'http:', hostname: address.address, port: address.port })
77
+ : format({ protocol: 'http:', hostname: host, port }));
78
+ console.log(`Listening on ${url}`);
79
+ });
80
+ if (activation) server.listen({ fd: 3 }, () => console.log('Listening on file descriptor 3'));
81
+ else if (socket) clearStaleSocket(socket, bind);
82
+ else bind();
83
+ return server;
84
+ }
85
+
86
+ function socketInode(path: string): number | null {
87
+ try {
88
+ const stats = statSync(path);
89
+ return stats.isSocket() ? stats.ino : null;
90
+ } catch (error) {
91
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
92
+ return null;
93
+ }
94
+ }
95
+
96
+ function clearStaleSocket(path: string, then: () => void): void {
97
+ const stale = socketInode(path);
98
+ if (stale === null) return then();
99
+ const probe = connect({ path });
100
+ probe.once('connect', () => {
101
+ probe.destroy();
102
+ then();
103
+ });
104
+ probe.once('error', (error: NodeJS.ErrnoException) => {
105
+ if (error.code === 'ECONNREFUSED' && socketInode(path) === stale)
106
+ try {
107
+ unlinkSync(path);
108
+ } catch (error) {
109
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
110
+ }
111
+ then();
112
+ });
113
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.