@sveltejs/adapter-netlify 1.0.0-next.35 → 1.0.0-next.39
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.
- package/README.md +8 -38
- package/files/cjs/handler-a1088edc.js +6610 -0
- package/files/cjs/handler.js +17 -0
- package/files/cjs/multipart-parser-bdb1e34b.js +452 -0
- package/files/esm/handler-f0da68a1.js +6599 -0
- package/files/esm/handler.js +9 -0
- package/files/esm/multipart-parser-30e27ad5.js +450 -0
- package/index.d.ts +1 -6
- package/index.js +171 -54
- package/package.json +13 -3
- package/files/entry.js +0 -71
- package/files/shims.js +0 -1
package/index.js
CHANGED
|
@@ -1,83 +1,164 @@
|
|
|
1
1
|
import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import glob from 'tiny-glob/sync.js';
|
|
4
5
|
import esbuild from 'esbuild';
|
|
5
6
|
import toml from '@iarna/toml';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* @typedef {
|
|
9
|
+
* @typedef {{
|
|
10
|
+
* build?: { publish?: string }
|
|
11
|
+
* functions?: { node_bundler?: 'zisi' | 'esbuild' }
|
|
12
|
+
* } & toml.JsonMap} NetlifyConfig
|
|
9
13
|
*/
|
|
10
14
|
|
|
15
|
+
const files = fileURLToPath(new URL('./files', import.meta.url));
|
|
16
|
+
|
|
11
17
|
/** @type {import('.')} */
|
|
12
|
-
export default function (
|
|
18
|
+
export default function ({ split = false } = {}) {
|
|
13
19
|
return {
|
|
14
20
|
name: '@sveltejs/adapter-netlify',
|
|
15
21
|
|
|
16
|
-
async adapt(
|
|
17
|
-
|
|
18
|
-
const publish = get_publish_directory(utils) || 'build';
|
|
19
|
-
|
|
20
|
-
utils.log.minor(`Publishing to "${publish}"`);
|
|
21
|
-
|
|
22
|
-
utils.rimraf(publish);
|
|
22
|
+
async adapt(builder) {
|
|
23
|
+
const netlify_config = get_netlify_config();
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
utils.log.minor('Generating serverless function...');
|
|
27
|
-
utils.copy(join(files, 'entry.js'), '.svelte-kit/netlify/entry.js');
|
|
28
|
-
|
|
29
|
-
/** @type {BuildOptions} */
|
|
30
|
-
const default_options = {
|
|
31
|
-
entryPoints: ['.svelte-kit/netlify/entry.js'],
|
|
32
|
-
// Any functions in ".netlify/functions-internal" are bundled in addition to user-defined Netlify functions.
|
|
33
|
-
// See https://github.com/netlify/build/pull/3213 for more details
|
|
34
|
-
outfile: '.netlify/functions-internal/__render.js',
|
|
35
|
-
bundle: true,
|
|
36
|
-
inject: [join(files, 'shims.js')],
|
|
37
|
-
platform: 'node'
|
|
38
|
-
};
|
|
25
|
+
// "build" is the default publish directory when Netlify detects SvelteKit
|
|
26
|
+
const publish = get_publish_directory(netlify_config, builder) || 'build';
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
// empty out existing build directories
|
|
29
|
+
builder.rimraf(publish);
|
|
30
|
+
builder.rimraf('.netlify/functions-internal');
|
|
31
|
+
builder.rimraf('.netlify/server');
|
|
32
|
+
builder.rimraf('.netlify/package.json');
|
|
33
|
+
builder.rimraf('.netlify/handler.js');
|
|
42
34
|
|
|
43
|
-
|
|
35
|
+
builder.mkdirp('.netlify/functions-internal');
|
|
44
36
|
|
|
45
|
-
|
|
37
|
+
builder.log.minor(`Publishing to "${publish}"`);
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
await
|
|
39
|
+
builder.log.minor('Prerendering static pages...');
|
|
40
|
+
await builder.prerender({
|
|
49
41
|
dest: publish
|
|
50
42
|
});
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
builder.writeServer('.netlify/server');
|
|
45
|
+
|
|
46
|
+
// for esbuild, use ESM
|
|
47
|
+
// for zip-it-and-ship-it, use CJS until https://github.com/netlify/zip-it-and-ship-it/issues/750
|
|
48
|
+
const esm = netlify_config?.functions?.node_bundler === 'esbuild';
|
|
49
|
+
|
|
50
|
+
/** @type {string[]} */
|
|
51
|
+
const redirects = [];
|
|
52
|
+
|
|
53
|
+
if (esm) {
|
|
54
|
+
builder.copy(`${files}/esm`, '.netlify');
|
|
55
|
+
} else {
|
|
56
|
+
glob('**/*.js', { cwd: '.netlify/server' }).forEach((file) => {
|
|
57
|
+
const filepath = `.netlify/server/${file}`;
|
|
58
|
+
const input = readFileSync(filepath, 'utf8');
|
|
59
|
+
const output = esbuild.transformSync(input, { format: 'cjs', target: 'node12' }).code;
|
|
60
|
+
writeFileSync(filepath, output);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
builder.copy(`${files}/cjs`, '.netlify');
|
|
64
|
+
writeFileSync(join('.netlify', 'package.json'), JSON.stringify({ type: 'commonjs' }));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (split) {
|
|
68
|
+
builder.log.minor('Generating serverless functions...');
|
|
69
|
+
|
|
70
|
+
builder.createEntries((route) => {
|
|
71
|
+
const parts = [];
|
|
72
|
+
|
|
73
|
+
for (const segment of route.segments) {
|
|
74
|
+
if (segment.rest) {
|
|
75
|
+
parts.push('*');
|
|
76
|
+
break; // Netlify redirects don't allow anything after a *
|
|
77
|
+
} else if (segment.dynamic) {
|
|
78
|
+
parts.push(`:${parts.length}`);
|
|
79
|
+
} else {
|
|
80
|
+
parts.push(segment.content);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const pattern = `/${parts.join('/')}`;
|
|
85
|
+
const name = parts.join('-').replace(/[:.]/g, '_').replace('*', '__rest') || 'index';
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
id: pattern,
|
|
89
|
+
filter: (other) => matches(route.segments, other.segments),
|
|
90
|
+
complete: (entry) => {
|
|
91
|
+
const manifest = entry.generateManifest({
|
|
92
|
+
relativePath: '../server',
|
|
93
|
+
format: esm ? 'esm' : 'cjs'
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const fn = esm
|
|
97
|
+
? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
|
|
98
|
+
: `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
|
|
99
|
+
|
|
100
|
+
writeFileSync(`.netlify/functions-internal/${name}.js`, fn);
|
|
101
|
+
|
|
102
|
+
redirects.push(`${pattern} /.netlify/functions/${name} 200`);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
} else {
|
|
107
|
+
builder.log.minor('Generating serverless functions...');
|
|
108
|
+
|
|
109
|
+
const manifest = builder.generateManifest({
|
|
110
|
+
relativePath: '../server',
|
|
111
|
+
format: esm ? 'esm' : 'cjs'
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const fn = esm
|
|
115
|
+
? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
|
|
116
|
+
: `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
|
|
117
|
+
|
|
118
|
+
writeFileSync('.netlify/functions-internal/render.js', fn);
|
|
119
|
+
|
|
120
|
+
redirects.push('* /.netlify/functions/render 200');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
builder.log.minor('Copying assets...');
|
|
124
|
+
builder.writeStatic(publish);
|
|
125
|
+
builder.writeClient(publish);
|
|
126
|
+
|
|
127
|
+
builder.log.minor('Writing redirects...');
|
|
128
|
+
const redirect_file = join(publish, '_redirects');
|
|
129
|
+
builder.copy('_redirects', redirect_file);
|
|
130
|
+
appendFileSync(redirect_file, `\n\n${redirects.join('\n')}`);
|
|
131
|
+
|
|
132
|
+
builder.log.minor('Writing custom headers...');
|
|
133
|
+
const headers_file = join(publish, '_headers');
|
|
134
|
+
builder.copy('_headers', headers_file);
|
|
135
|
+
appendFileSync(
|
|
136
|
+
headers_file,
|
|
137
|
+
`\n\n/${builder.appDir}/*\n cache-control: public\n cache-control: immutable\n cache-control: max-age=31536000\n`
|
|
138
|
+
);
|
|
61
139
|
}
|
|
62
140
|
};
|
|
63
141
|
}
|
|
142
|
+
|
|
143
|
+
function get_netlify_config() {
|
|
144
|
+
if (!existsSync('netlify.toml')) return null;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
return /** @type {NetlifyConfig} */ (toml.parse(readFileSync('netlify.toml', 'utf-8')));
|
|
148
|
+
} catch (err) {
|
|
149
|
+
err.message = `Error parsing netlify.toml: ${err.message}`;
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
64
154
|
/**
|
|
65
|
-
* @param {
|
|
155
|
+
* @param {NetlifyConfig} netlify_config
|
|
156
|
+
* @param {import('@sveltejs/kit').Builder} builder
|
|
66
157
|
**/
|
|
67
|
-
function get_publish_directory(
|
|
68
|
-
if (
|
|
69
|
-
/** @type {{ build?: { publish?: string }} & toml.JsonMap } */
|
|
70
|
-
let netlify_config;
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
netlify_config = toml.parse(readFileSync('netlify.toml', 'utf-8'));
|
|
74
|
-
} catch (err) {
|
|
75
|
-
err.message = `Error parsing netlify.toml: ${err.message}`;
|
|
76
|
-
throw err;
|
|
77
|
-
}
|
|
78
|
-
|
|
158
|
+
function get_publish_directory(netlify_config, builder) {
|
|
159
|
+
if (netlify_config) {
|
|
79
160
|
if (!netlify_config.build || !netlify_config.build.publish) {
|
|
80
|
-
|
|
161
|
+
builder.log.warn('No publish directory specified in netlify.toml, using default');
|
|
81
162
|
return;
|
|
82
163
|
}
|
|
83
164
|
|
|
@@ -94,7 +175,43 @@ function get_publish_directory(utils) {
|
|
|
94
175
|
return netlify_config.build.publish;
|
|
95
176
|
}
|
|
96
177
|
|
|
97
|
-
|
|
178
|
+
builder.log.warn(
|
|
98
179
|
'No netlify.toml found. Using default publish directory. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration for more details '
|
|
99
180
|
);
|
|
100
181
|
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @typedef {{ rest: boolean, dynamic: boolean, content: string }} RouteSegment
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @param {RouteSegment[]} a
|
|
189
|
+
* @param {RouteSegment[]} b
|
|
190
|
+
* @returns {boolean}
|
|
191
|
+
*/
|
|
192
|
+
function matches(a, b) {
|
|
193
|
+
if (a[0] && b[0]) {
|
|
194
|
+
if (b[0].rest) {
|
|
195
|
+
if (b.length === 1) return true;
|
|
196
|
+
|
|
197
|
+
const next_b = b.slice(1);
|
|
198
|
+
|
|
199
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
200
|
+
if (matches(a.slice(i), next_b)) return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!b[0].dynamic) {
|
|
207
|
+
if (!a[0].dynamic && a[0].content !== b[0].content) return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (a.length === 1 && b.length === 1) return true;
|
|
211
|
+
return matches(a.slice(1), b.slice(1));
|
|
212
|
+
} else if (a[0]) {
|
|
213
|
+
return a.length === 1 && a[0].rest;
|
|
214
|
+
} else {
|
|
215
|
+
return b.length === 1 && b[0].rest;
|
|
216
|
+
}
|
|
217
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/adapter-netlify",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.39",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
7
7
|
"directory": "packages/adapter-netlify"
|
|
8
8
|
},
|
|
9
|
+
"license": "MIT",
|
|
9
10
|
"homepage": "https://kit.svelte.dev",
|
|
10
11
|
"type": "module",
|
|
11
12
|
"exports": {
|
|
@@ -22,12 +23,21 @@
|
|
|
22
23
|
],
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"@iarna/toml": "^2.2.5",
|
|
25
|
-
"esbuild": "^0.13.
|
|
26
|
+
"esbuild": "^0.13.15",
|
|
27
|
+
"tiny-glob": "^0.2.9"
|
|
26
28
|
},
|
|
27
29
|
"devDependencies": {
|
|
28
|
-
"@
|
|
30
|
+
"@netlify/functions": "^0.10.0",
|
|
31
|
+
"@rollup/plugin-commonjs": "^21.0.0",
|
|
32
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
33
|
+
"@rollup/plugin-node-resolve": "^13.0.5",
|
|
34
|
+
"@sveltejs/kit": "1.0.0-next.232",
|
|
35
|
+
"rimraf": "^3.0.2",
|
|
36
|
+
"rollup": "^2.58.0"
|
|
29
37
|
},
|
|
30
38
|
"scripts": {
|
|
39
|
+
"dev": "rimraf files && rollup -cw",
|
|
40
|
+
"build": "rimraf files && rollup -c",
|
|
31
41
|
"lint": "eslint --ignore-path .gitignore \"**/*.{ts,js,svelte}\" && npm run check-format",
|
|
32
42
|
"format": "npm run check-format -- --write",
|
|
33
43
|
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore"
|
package/files/entry.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// TODO hardcoding the relative location makes this brittle
|
|
2
|
-
import { init, render } from '../output/server/app.js';
|
|
3
|
-
|
|
4
|
-
init();
|
|
5
|
-
|
|
6
|
-
export async function handler(event) {
|
|
7
|
-
const { path, httpMethod, headers, rawQuery, body, isBase64Encoded } = event;
|
|
8
|
-
|
|
9
|
-
const query = new URLSearchParams(rawQuery);
|
|
10
|
-
|
|
11
|
-
const encoding = isBase64Encoded ? 'base64' : headers['content-encoding'] || 'utf-8';
|
|
12
|
-
const rawBody = typeof body === 'string' ? Buffer.from(body, encoding) : body;
|
|
13
|
-
|
|
14
|
-
const rendered = await render({
|
|
15
|
-
method: httpMethod,
|
|
16
|
-
headers,
|
|
17
|
-
path,
|
|
18
|
-
query,
|
|
19
|
-
rawBody
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
if (!rendered) {
|
|
23
|
-
return {
|
|
24
|
-
statusCode: 404,
|
|
25
|
-
body: 'Not found'
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const partial_response = {
|
|
30
|
-
statusCode: rendered.status,
|
|
31
|
-
...split_headers(rendered.headers)
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
if (rendered.body instanceof Uint8Array) {
|
|
35
|
-
// Function responses should always be strings, and responses with binary
|
|
36
|
-
// content should be base64 encoded and set isBase64Encoded to true.
|
|
37
|
-
// https://github.com/netlify/functions/blob/main/src/function/response.d.ts
|
|
38
|
-
return {
|
|
39
|
-
...partial_response,
|
|
40
|
-
isBase64Encoded: true,
|
|
41
|
-
body: Buffer.from(rendered.body).toString('base64')
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
...partial_response,
|
|
47
|
-
body: rendered.body
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Splits headers into two categories: single value and multi value
|
|
53
|
-
* @param {Record<string, string | string[]>} headers
|
|
54
|
-
* @returns {{
|
|
55
|
-
* headers: Record<string, string>,
|
|
56
|
-
* multiValueHeaders: Record<string, string[]>
|
|
57
|
-
* }}
|
|
58
|
-
*/
|
|
59
|
-
function split_headers(headers) {
|
|
60
|
-
const h = {};
|
|
61
|
-
const m = {};
|
|
62
|
-
for (const key in headers) {
|
|
63
|
-
const value = headers[key];
|
|
64
|
-
const target = Array.isArray(value) ? m : h;
|
|
65
|
-
target[key] = value;
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
headers: h,
|
|
69
|
-
multiValueHeaders: m
|
|
70
|
-
};
|
|
71
|
-
}
|
package/files/shims.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { fetch, Response, Request, Headers } from '@sveltejs/kit/install-fetch';
|