@sveltejs/adapter-netlify 5.2.4 → 6.0.2
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/ambient.d.ts +9 -0
- package/files/serverless.js +4 -331
- package/index.d.ts +1 -0
- package/index.js +72 -69
- package/package.json +14 -12
package/ambient.d.ts
ADDED
package/files/serverless.js
CHANGED
|
@@ -6,273 +6,6 @@ import process from 'node:process';
|
|
|
6
6
|
import 'node:buffer';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
|
|
9
|
-
var setCookie = {exports: {}};
|
|
10
|
-
|
|
11
|
-
var hasRequiredSetCookie;
|
|
12
|
-
|
|
13
|
-
function requireSetCookie () {
|
|
14
|
-
if (hasRequiredSetCookie) return setCookie.exports;
|
|
15
|
-
hasRequiredSetCookie = 1;
|
|
16
|
-
|
|
17
|
-
var defaultParseOptions = {
|
|
18
|
-
decodeValues: true,
|
|
19
|
-
map: false,
|
|
20
|
-
silent: false,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
function isNonEmptyString(str) {
|
|
24
|
-
return typeof str === "string" && !!str.trim();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function parseString(setCookieValue, options) {
|
|
28
|
-
var parts = setCookieValue.split(";").filter(isNonEmptyString);
|
|
29
|
-
|
|
30
|
-
var nameValuePairStr = parts.shift();
|
|
31
|
-
var parsed = parseNameValuePair(nameValuePairStr);
|
|
32
|
-
var name = parsed.name;
|
|
33
|
-
var value = parsed.value;
|
|
34
|
-
|
|
35
|
-
options = options
|
|
36
|
-
? Object.assign({}, defaultParseOptions, options)
|
|
37
|
-
: defaultParseOptions;
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
value = options.decodeValues ? decodeURIComponent(value) : value; // decode cookie value
|
|
41
|
-
} catch (e) {
|
|
42
|
-
console.error(
|
|
43
|
-
"set-cookie-parser encountered an error while decoding a cookie with value '" +
|
|
44
|
-
value +
|
|
45
|
-
"'. Set options.decodeValues to false to disable this feature.",
|
|
46
|
-
e
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
var cookie = {
|
|
51
|
-
name: name,
|
|
52
|
-
value: value,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
parts.forEach(function (part) {
|
|
56
|
-
var sides = part.split("=");
|
|
57
|
-
var key = sides.shift().trimLeft().toLowerCase();
|
|
58
|
-
var value = sides.join("=");
|
|
59
|
-
if (key === "expires") {
|
|
60
|
-
cookie.expires = new Date(value);
|
|
61
|
-
} else if (key === "max-age") {
|
|
62
|
-
cookie.maxAge = parseInt(value, 10);
|
|
63
|
-
} else if (key === "secure") {
|
|
64
|
-
cookie.secure = true;
|
|
65
|
-
} else if (key === "httponly") {
|
|
66
|
-
cookie.httpOnly = true;
|
|
67
|
-
} else if (key === "samesite") {
|
|
68
|
-
cookie.sameSite = value;
|
|
69
|
-
} else {
|
|
70
|
-
cookie[key] = value;
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return cookie;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function parseNameValuePair(nameValuePairStr) {
|
|
78
|
-
// Parses name-value-pair according to rfc6265bis draft
|
|
79
|
-
|
|
80
|
-
var name = "";
|
|
81
|
-
var value = "";
|
|
82
|
-
var nameValueArr = nameValuePairStr.split("=");
|
|
83
|
-
if (nameValueArr.length > 1) {
|
|
84
|
-
name = nameValueArr.shift();
|
|
85
|
-
value = nameValueArr.join("="); // everything after the first =, joined by a "=" if there was more than one part
|
|
86
|
-
} else {
|
|
87
|
-
value = nameValuePairStr;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return { name: name, value: value };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function parse(input, options) {
|
|
94
|
-
options = options
|
|
95
|
-
? Object.assign({}, defaultParseOptions, options)
|
|
96
|
-
: defaultParseOptions;
|
|
97
|
-
|
|
98
|
-
if (!input) {
|
|
99
|
-
if (!options.map) {
|
|
100
|
-
return [];
|
|
101
|
-
} else {
|
|
102
|
-
return {};
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (input.headers) {
|
|
107
|
-
if (typeof input.headers.getSetCookie === "function") {
|
|
108
|
-
// for fetch responses - they combine headers of the same type in the headers array,
|
|
109
|
-
// but getSetCookie returns an uncombined array
|
|
110
|
-
input = input.headers.getSetCookie();
|
|
111
|
-
} else if (input.headers["set-cookie"]) {
|
|
112
|
-
// fast-path for node.js (which automatically normalizes header names to lower-case
|
|
113
|
-
input = input.headers["set-cookie"];
|
|
114
|
-
} else {
|
|
115
|
-
// slow-path for other environments - see #25
|
|
116
|
-
var sch =
|
|
117
|
-
input.headers[
|
|
118
|
-
Object.keys(input.headers).find(function (key) {
|
|
119
|
-
return key.toLowerCase() === "set-cookie";
|
|
120
|
-
})
|
|
121
|
-
];
|
|
122
|
-
// warn if called on a request-like object with a cookie header rather than a set-cookie header - see #34, 36
|
|
123
|
-
if (!sch && input.headers.cookie && !options.silent) {
|
|
124
|
-
console.warn(
|
|
125
|
-
"Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning."
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
input = sch;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
if (!Array.isArray(input)) {
|
|
132
|
-
input = [input];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
options = options
|
|
136
|
-
? Object.assign({}, defaultParseOptions, options)
|
|
137
|
-
: defaultParseOptions;
|
|
138
|
-
|
|
139
|
-
if (!options.map) {
|
|
140
|
-
return input.filter(isNonEmptyString).map(function (str) {
|
|
141
|
-
return parseString(str, options);
|
|
142
|
-
});
|
|
143
|
-
} else {
|
|
144
|
-
var cookies = {};
|
|
145
|
-
return input.filter(isNonEmptyString).reduce(function (cookies, str) {
|
|
146
|
-
var cookie = parseString(str, options);
|
|
147
|
-
cookies[cookie.name] = cookie;
|
|
148
|
-
return cookies;
|
|
149
|
-
}, cookies);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/*
|
|
154
|
-
Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
|
|
155
|
-
that are within a single set-cookie field-value, such as in the Expires portion.
|
|
156
|
-
|
|
157
|
-
This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2
|
|
158
|
-
Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128
|
|
159
|
-
React Native's fetch does this for *every* header, including set-cookie.
|
|
160
|
-
|
|
161
|
-
Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25
|
|
162
|
-
Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation
|
|
163
|
-
*/
|
|
164
|
-
function splitCookiesString(cookiesString) {
|
|
165
|
-
if (Array.isArray(cookiesString)) {
|
|
166
|
-
return cookiesString;
|
|
167
|
-
}
|
|
168
|
-
if (typeof cookiesString !== "string") {
|
|
169
|
-
return [];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
var cookiesStrings = [];
|
|
173
|
-
var pos = 0;
|
|
174
|
-
var start;
|
|
175
|
-
var ch;
|
|
176
|
-
var lastComma;
|
|
177
|
-
var nextStart;
|
|
178
|
-
var cookiesSeparatorFound;
|
|
179
|
-
|
|
180
|
-
function skipWhitespace() {
|
|
181
|
-
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
|
182
|
-
pos += 1;
|
|
183
|
-
}
|
|
184
|
-
return pos < cookiesString.length;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function notSpecialChar() {
|
|
188
|
-
ch = cookiesString.charAt(pos);
|
|
189
|
-
|
|
190
|
-
return ch !== "=" && ch !== ";" && ch !== ",";
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
while (pos < cookiesString.length) {
|
|
194
|
-
start = pos;
|
|
195
|
-
cookiesSeparatorFound = false;
|
|
196
|
-
|
|
197
|
-
while (skipWhitespace()) {
|
|
198
|
-
ch = cookiesString.charAt(pos);
|
|
199
|
-
if (ch === ",") {
|
|
200
|
-
// ',' is a cookie separator if we have later first '=', not ';' or ','
|
|
201
|
-
lastComma = pos;
|
|
202
|
-
pos += 1;
|
|
203
|
-
|
|
204
|
-
skipWhitespace();
|
|
205
|
-
nextStart = pos;
|
|
206
|
-
|
|
207
|
-
while (pos < cookiesString.length && notSpecialChar()) {
|
|
208
|
-
pos += 1;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// currently special character
|
|
212
|
-
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
|
213
|
-
// we found cookies separator
|
|
214
|
-
cookiesSeparatorFound = true;
|
|
215
|
-
// pos is inside the next cookie, so back up and return it.
|
|
216
|
-
pos = nextStart;
|
|
217
|
-
cookiesStrings.push(cookiesString.substring(start, lastComma));
|
|
218
|
-
start = pos;
|
|
219
|
-
} else {
|
|
220
|
-
// in param ',' or param separator ';',
|
|
221
|
-
// we continue from that comma
|
|
222
|
-
pos = lastComma + 1;
|
|
223
|
-
}
|
|
224
|
-
} else {
|
|
225
|
-
pos += 1;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
|
230
|
-
cookiesStrings.push(cookiesString.substring(start, cookiesString.length));
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return cookiesStrings;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
setCookie.exports = parse;
|
|
238
|
-
setCookie.exports.parse = parse;
|
|
239
|
-
setCookie.exports.parseString = parseString;
|
|
240
|
-
setCookie.exports.splitCookiesString = splitCookiesString;
|
|
241
|
-
return setCookie.exports;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
var setCookieExports = /*@__PURE__*/ requireSetCookie();
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Splits headers into two categories: single value and multi value
|
|
248
|
-
* @param {Headers} headers
|
|
249
|
-
* @returns {{
|
|
250
|
-
* headers: Record<string, string>,
|
|
251
|
-
* multiValueHeaders: Record<string, string[]>
|
|
252
|
-
* }}
|
|
253
|
-
*/
|
|
254
|
-
function split_headers(headers) {
|
|
255
|
-
/** @type {Record<string, string>} */
|
|
256
|
-
const h = {};
|
|
257
|
-
|
|
258
|
-
/** @type {Record<string, string[]>} */
|
|
259
|
-
const m = {};
|
|
260
|
-
|
|
261
|
-
headers.forEach((value, key) => {
|
|
262
|
-
if (key === 'set-cookie') {
|
|
263
|
-
if (!m[key]) m[key] = [];
|
|
264
|
-
m[key].push(...setCookieExports.splitCookiesString(value));
|
|
265
|
-
} else {
|
|
266
|
-
h[key] = value;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
return {
|
|
271
|
-
headers: h,
|
|
272
|
-
multiValueHeaders: m
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
|
|
276
9
|
/**
|
|
277
10
|
* Converts a file on disk to a readable stream
|
|
278
11
|
* @param {string} file
|
|
@@ -285,7 +18,7 @@ function createReadableStream(file) {
|
|
|
285
18
|
|
|
286
19
|
/**
|
|
287
20
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
288
|
-
* @returns {import('@netlify/functions').
|
|
21
|
+
* @returns {(request: Request, context: import('@netlify/functions').Context) => Promise<Response>}
|
|
289
22
|
*/
|
|
290
23
|
function init(manifest) {
|
|
291
24
|
const server = new Server(manifest);
|
|
@@ -296,79 +29,19 @@ function init(manifest) {
|
|
|
296
29
|
read: (file) => createReadableStream(`.netlify/server/${file}`)
|
|
297
30
|
});
|
|
298
31
|
|
|
299
|
-
return async (
|
|
32
|
+
return async (request, context) => {
|
|
300
33
|
if (init_promise !== null) {
|
|
301
34
|
await init_promise;
|
|
302
35
|
init_promise = null;
|
|
303
36
|
}
|
|
304
37
|
|
|
305
|
-
|
|
38
|
+
return server.respond(request, {
|
|
306
39
|
platform: { context },
|
|
307
40
|
getClientAddress() {
|
|
308
|
-
return
|
|
41
|
+
return context.ip;
|
|
309
42
|
}
|
|
310
43
|
});
|
|
311
|
-
|
|
312
|
-
const partial_response = {
|
|
313
|
-
statusCode: response.status,
|
|
314
|
-
...split_headers(response.headers)
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
if (!is_text(response.headers.get('content-type'))) {
|
|
318
|
-
// Function responses should be strings (or undefined), and responses with binary
|
|
319
|
-
// content should be base64 encoded and set isBase64Encoded to true.
|
|
320
|
-
// https://github.com/netlify/functions/blob/main/src/function/response.ts
|
|
321
|
-
return {
|
|
322
|
-
...partial_response,
|
|
323
|
-
isBase64Encoded: true,
|
|
324
|
-
body: Buffer.from(await response.arrayBuffer()).toString('base64')
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return {
|
|
329
|
-
...partial_response,
|
|
330
|
-
body: await response.text()
|
|
331
|
-
};
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* @param {import('@netlify/functions').HandlerEvent} event
|
|
337
|
-
* @returns {Request}
|
|
338
|
-
*/
|
|
339
|
-
function to_request({ httpMethod, headers, rawUrl, body, isBase64Encoded }) {
|
|
340
|
-
/** @type {RequestInit} */
|
|
341
|
-
const init = {
|
|
342
|
-
method: httpMethod,
|
|
343
|
-
headers: new Headers(/** @type {Record<string, string>} */ (headers))
|
|
344
44
|
};
|
|
345
|
-
|
|
346
|
-
if (httpMethod !== 'GET' && httpMethod !== 'HEAD') {
|
|
347
|
-
const encoding = isBase64Encoded ? 'base64' : 'utf-8';
|
|
348
|
-
init.body = typeof body === 'string' ? Buffer.from(body, encoding) : body;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
return new Request(rawUrl, init);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const text_types = new Set([
|
|
355
|
-
'application/xml',
|
|
356
|
-
'application/json',
|
|
357
|
-
'application/x-www-form-urlencoded',
|
|
358
|
-
'multipart/form-data'
|
|
359
|
-
]);
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Decides how the body should be parsed based on its mime type
|
|
363
|
-
*
|
|
364
|
-
* @param {string | undefined | null} content_type The `content-type` header of a request/response.
|
|
365
|
-
* @returns {boolean}
|
|
366
|
-
*/
|
|
367
|
-
function is_text(content_type) {
|
|
368
|
-
if (!content_type) return true; // defaults to json
|
|
369
|
-
const type = content_type.split(';')[0].toLowerCase(); // get the mime type
|
|
370
|
-
|
|
371
|
-
return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type);
|
|
372
45
|
}
|
|
373
46
|
|
|
374
47
|
export { init };
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
/** @import { BuildOptions } from 'esbuild' */
|
|
2
2
|
import { appendFileSync, existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import {
|
|
3
|
+
import { join, resolve, posix } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { builtinModules } from 'node:module';
|
|
6
6
|
import process from 'node:process';
|
|
7
7
|
import esbuild from 'esbuild';
|
|
8
8
|
import toml from '@iarna/toml';
|
|
9
|
-
import { VERSION } from '@sveltejs/kit';
|
|
10
|
-
|
|
11
|
-
const [kit_major, kit_minor] = VERSION.split('.');
|
|
12
9
|
|
|
13
10
|
/**
|
|
14
11
|
* @typedef {{
|
|
@@ -17,17 +14,6 @@ const [kit_major, kit_minor] = VERSION.split('.');
|
|
|
17
14
|
* } & toml.JsonMap} NetlifyConfig
|
|
18
15
|
*/
|
|
19
16
|
|
|
20
|
-
/**
|
|
21
|
-
* @template T
|
|
22
|
-
* @template {keyof T} K
|
|
23
|
-
* @typedef {Partial<Omit<T, K>> & Required<Pick<T, K>>} PartialExcept
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* We use a custom `Builder` type here to support the minimum version of SvelteKit.
|
|
28
|
-
* @typedef {PartialExcept<import('@sveltejs/kit').Builder, 'log' | 'rimraf' | 'mkdirp' | 'config' | 'prerendered' | 'routes' | 'createEntries' | 'findServerAssets' | 'generateFallback' | 'generateEnvModule' | 'generateManifest' | 'getBuildDirectory' | 'getClientDirectory' | 'getServerDirectory' | 'getAppPath' | 'writeClient' | 'writePrerendered' | 'writePrerendered' | 'writeServer' | 'copy' | 'compress'>} Builder2_4_0
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
17
|
const name = '@sveltejs/adapter-netlify';
|
|
32
18
|
const files = fileURLToPath(new URL('./files', import.meta.url).href);
|
|
33
19
|
|
|
@@ -41,7 +27,7 @@ const FUNCTION_PREFIX = 'sveltekit-';
|
|
|
41
27
|
export default function ({ split = false, edge = edge_set_in_env_var } = {}) {
|
|
42
28
|
return {
|
|
43
29
|
name,
|
|
44
|
-
/** @param {
|
|
30
|
+
/** @param {import('@sveltejs/kit').Builder} builder */
|
|
45
31
|
async adapt(builder) {
|
|
46
32
|
if (!builder.routes) {
|
|
47
33
|
throw new Error(
|
|
@@ -109,23 +95,14 @@ export default function ({ split = false, edge = edge_set_in_env_var } = {}) {
|
|
|
109
95
|
},
|
|
110
96
|
|
|
111
97
|
supports: {
|
|
112
|
-
read: (
|
|
113
|
-
// TODO bump peer dep in next adapter major to simplify this
|
|
114
|
-
if (edge && kit_major === '2' && kit_minor < '25') {
|
|
115
|
-
throw new Error(
|
|
116
|
-
`${name}: Cannot use \`read\` from \`$app/server\` in route \`${route.id}\` when using edge functions and SvelteKit < 2.25.0`
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return true;
|
|
121
|
-
},
|
|
98
|
+
read: () => true,
|
|
122
99
|
instrumentation: () => true
|
|
123
100
|
}
|
|
124
101
|
};
|
|
125
102
|
}
|
|
126
103
|
/**
|
|
127
104
|
* @param { object } params
|
|
128
|
-
* @param {
|
|
105
|
+
* @param {import('@sveltejs/kit').Builder} params.builder
|
|
129
106
|
*/
|
|
130
107
|
async function generate_edge_functions({ builder }) {
|
|
131
108
|
const tmp = builder.getBuildDirectory('netlify-tmp');
|
|
@@ -214,7 +191,7 @@ async function generate_edge_functions({ builder }) {
|
|
|
214
191
|
outfile: '.netlify/edge-functions/render.js',
|
|
215
192
|
...esbuild_config
|
|
216
193
|
}),
|
|
217
|
-
builder.hasServerInstrumentationFile
|
|
194
|
+
builder.hasServerInstrumentationFile() &&
|
|
218
195
|
esbuild.build({
|
|
219
196
|
entryPoints: [`${builder.getServerDirectory()}/instrumentation.server.js`],
|
|
220
197
|
outfile: '.netlify/edge/instrumentation.server.js',
|
|
@@ -222,8 +199,8 @@ async function generate_edge_functions({ builder }) {
|
|
|
222
199
|
})
|
|
223
200
|
]);
|
|
224
201
|
|
|
225
|
-
if (builder.hasServerInstrumentationFile
|
|
226
|
-
builder.instrument
|
|
202
|
+
if (builder.hasServerInstrumentationFile()) {
|
|
203
|
+
builder.instrument({
|
|
227
204
|
entrypoint: '.netlify/edge-functions/render.js',
|
|
228
205
|
instrumentation: '.netlify/edge/instrumentation.server.js',
|
|
229
206
|
start: '.netlify/edge/start.js'
|
|
@@ -234,25 +211,20 @@ async function generate_edge_functions({ builder }) {
|
|
|
234
211
|
}
|
|
235
212
|
/**
|
|
236
213
|
* @param { object } params
|
|
237
|
-
* @param {
|
|
214
|
+
* @param {import('@sveltejs/kit').Builder} params.builder
|
|
238
215
|
* @param { string } params.publish
|
|
239
216
|
* @param { boolean } params.split
|
|
240
217
|
*/
|
|
241
218
|
function generate_lambda_functions({ builder, publish, split }) {
|
|
242
219
|
builder.mkdirp('.netlify/functions-internal/.svelte-kit');
|
|
243
220
|
|
|
244
|
-
/** @type {string[]} */
|
|
245
|
-
const redirects = [];
|
|
246
221
|
builder.writeServer('.netlify/server');
|
|
247
222
|
|
|
248
223
|
const replace = {
|
|
249
224
|
'0SERVER': './server/index.js' // digit prefix prevents CJS build from using this as a variable name, which would also get replaced
|
|
250
225
|
};
|
|
251
226
|
|
|
252
|
-
builder.copy(files, '.netlify', { replace });
|
|
253
|
-
|
|
254
|
-
// Configuring the function to use ESM as the output format.
|
|
255
|
-
const fn_config = JSON.stringify({ config: { nodeModuleFormat: 'esm' }, version: 1 });
|
|
227
|
+
builder.copy(files, '.netlify', { replace, filter: (name) => !name.endsWith('edge.js') });
|
|
256
228
|
|
|
257
229
|
builder.log.minor('Generating serverless functions...');
|
|
258
230
|
|
|
@@ -273,7 +245,8 @@ function generate_lambda_functions({ builder, publish, split }) {
|
|
|
273
245
|
parts.push('*');
|
|
274
246
|
break; // Netlify redirects don't allow anything after a *
|
|
275
247
|
} else if (segment.dynamic) {
|
|
276
|
-
|
|
248
|
+
// URLPattern requires params to start with letters
|
|
249
|
+
parts.push(`:param${parts.length}`);
|
|
277
250
|
} else {
|
|
278
251
|
parts.push(segment.content);
|
|
279
252
|
}
|
|
@@ -302,58 +275,52 @@ function generate_lambda_functions({ builder, publish, split }) {
|
|
|
302
275
|
routes
|
|
303
276
|
});
|
|
304
277
|
|
|
305
|
-
const fn =
|
|
278
|
+
const fn = generate_serverless_function_module(manifest);
|
|
279
|
+
const config = generate_config_export(pattern);
|
|
306
280
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
builder.instrument?.({
|
|
281
|
+
if (builder.hasServerInstrumentationFile()) {
|
|
282
|
+
writeFileSync(`.netlify/functions-internal/${name}.mjs`, fn);
|
|
283
|
+
builder.instrument({
|
|
311
284
|
entrypoint: `.netlify/functions-internal/${name}.mjs`,
|
|
312
285
|
instrumentation: '.netlify/server/instrumentation.server.js',
|
|
313
286
|
start: `.netlify/functions-start/${name}.start.mjs`,
|
|
314
287
|
module: {
|
|
315
|
-
|
|
288
|
+
generateText: generate_traced_module(config)
|
|
316
289
|
}
|
|
317
290
|
});
|
|
291
|
+
} else {
|
|
292
|
+
writeFileSync(`.netlify/functions-internal/${name}.mjs`, `${fn}\n${config}`);
|
|
318
293
|
}
|
|
319
|
-
|
|
320
|
-
const redirect = `/.netlify/functions/${name} 200`;
|
|
321
|
-
redirects.push(`${pattern} ${redirect}`);
|
|
322
|
-
redirects.push(`${pattern === '/' ? '' : pattern}/__data.json ${redirect}`);
|
|
323
294
|
}
|
|
324
295
|
} else {
|
|
325
296
|
const manifest = builder.generateManifest({
|
|
326
297
|
relativePath: '../server'
|
|
327
298
|
});
|
|
328
299
|
|
|
329
|
-
const fn =
|
|
300
|
+
const fn = generate_serverless_function_module(manifest);
|
|
301
|
+
const config = generate_config_export('/*');
|
|
330
302
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
builder.instrument?.({
|
|
303
|
+
if (builder.hasServerInstrumentationFile()) {
|
|
304
|
+
writeFileSync(`.netlify/functions-internal/${FUNCTION_PREFIX}render.mjs`, fn);
|
|
305
|
+
builder.instrument({
|
|
335
306
|
entrypoint: `.netlify/functions-internal/${FUNCTION_PREFIX}render.mjs`,
|
|
336
307
|
instrumentation: '.netlify/server/instrumentation.server.js',
|
|
337
308
|
start: `.netlify/functions-start/${FUNCTION_PREFIX}render.start.mjs`,
|
|
338
309
|
module: {
|
|
339
|
-
|
|
310
|
+
generateText: generate_traced_module(config)
|
|
340
311
|
}
|
|
341
312
|
});
|
|
313
|
+
} else {
|
|
314
|
+
writeFileSync(`.netlify/functions-internal/${FUNCTION_PREFIX}render.mjs`, `${fn}\n${config}`);
|
|
342
315
|
}
|
|
343
|
-
|
|
344
|
-
redirects.push(`* /.netlify/functions/${FUNCTION_PREFIX}render 200`);
|
|
345
316
|
}
|
|
346
317
|
|
|
347
|
-
//
|
|
348
|
-
// so that generated redirects are appended to custom redirects
|
|
349
|
-
// rather than replaced by them
|
|
350
|
-
builder.log.minor('Writing redirects...');
|
|
351
|
-
const redirects_file = join(publish, '_redirects');
|
|
318
|
+
// Copy user's custom _redirects file if it exists
|
|
352
319
|
if (existsSync('_redirects')) {
|
|
320
|
+
builder.log.minor('Copying user redirects...');
|
|
321
|
+
const redirects_file = join(publish, '_redirects');
|
|
353
322
|
builder.copy('_redirects', redirects_file);
|
|
354
323
|
}
|
|
355
|
-
builder.mkdirp(dirname(redirects_file));
|
|
356
|
-
appendFileSync(redirects_file, `\n\n${redirects.join('\n')}`);
|
|
357
324
|
}
|
|
358
325
|
|
|
359
326
|
function get_netlify_config() {
|
|
@@ -369,7 +336,7 @@ function get_netlify_config() {
|
|
|
369
336
|
|
|
370
337
|
/**
|
|
371
338
|
* @param {NetlifyConfig | null} netlify_config
|
|
372
|
-
* @param {
|
|
339
|
+
* @param {import('@sveltejs/kit').Builder} builder
|
|
373
340
|
**/
|
|
374
341
|
function get_publish_directory(netlify_config, builder) {
|
|
375
342
|
if (netlify_config) {
|
|
@@ -378,11 +345,6 @@ function get_publish_directory(netlify_config, builder) {
|
|
|
378
345
|
return;
|
|
379
346
|
}
|
|
380
347
|
|
|
381
|
-
if (netlify_config.redirects) {
|
|
382
|
-
throw new Error(
|
|
383
|
-
"Redirects are not supported in netlify.toml. Use _redirects instead. For more details consult the readme's troubleshooting section."
|
|
384
|
-
);
|
|
385
|
-
}
|
|
386
348
|
if (resolve(netlify_config.build.publish) === process.cwd()) {
|
|
387
349
|
throw new Error(
|
|
388
350
|
'The publish directory cannot be set to the site root. Please change it to another value such as "build" in netlify.toml.'
|
|
@@ -431,3 +393,44 @@ function matches(a, b) {
|
|
|
431
393
|
return b.length === 1 && b[0].rest;
|
|
432
394
|
}
|
|
433
395
|
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* @param {string} manifest
|
|
399
|
+
* @returns {string}
|
|
400
|
+
*/
|
|
401
|
+
function generate_serverless_function_module(manifest) {
|
|
402
|
+
return `\
|
|
403
|
+
import { init } from '../serverless.js';
|
|
404
|
+
|
|
405
|
+
export default init(${manifest});
|
|
406
|
+
`;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @param {string} pattern
|
|
411
|
+
* @returns {string}
|
|
412
|
+
*/
|
|
413
|
+
function generate_config_export(pattern) {
|
|
414
|
+
return `\
|
|
415
|
+
export const config = {
|
|
416
|
+
path: "${pattern}",
|
|
417
|
+
excludedPath: "/.netlify/*",
|
|
418
|
+
preferStatic: true
|
|
419
|
+
};
|
|
420
|
+
`;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* @param {string} config
|
|
425
|
+
* @returns {(opts: { instrumentation: string; start: string }) => string}
|
|
426
|
+
*/
|
|
427
|
+
function generate_traced_module(config) {
|
|
428
|
+
return ({ instrumentation, start }) => {
|
|
429
|
+
return `\
|
|
430
|
+
import './${instrumentation}';
|
|
431
|
+
const { default: _0 } = await import('./${start}');
|
|
432
|
+
export { _0 as default };
|
|
433
|
+
|
|
434
|
+
${config}`;
|
|
435
|
+
};
|
|
436
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/adapter-netlify",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "A SvelteKit adapter that creates a Netlify app",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -29,29 +29,31 @@
|
|
|
29
29
|
"files": [
|
|
30
30
|
"files",
|
|
31
31
|
"index.js",
|
|
32
|
-
"index.d.ts"
|
|
32
|
+
"index.d.ts",
|
|
33
|
+
"ambient.d.ts"
|
|
33
34
|
],
|
|
34
35
|
"dependencies": {
|
|
35
36
|
"@iarna/toml": "^2.2.5",
|
|
36
|
-
"esbuild": "^0.25.4"
|
|
37
|
-
"set-cookie-parser": "^2.6.0"
|
|
37
|
+
"esbuild": "^0.25.4"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@netlify/
|
|
41
|
-
"@netlify/functions": "^
|
|
42
|
-
"@
|
|
40
|
+
"@netlify/dev": "^4.8.8",
|
|
41
|
+
"@netlify/edge-functions": "^3.0.0",
|
|
42
|
+
"@netlify/functions": "^5.0.0",
|
|
43
|
+
"@netlify/node-cookies": "^0.1.0",
|
|
44
|
+
"@netlify/types": "^2.1.0",
|
|
45
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
43
46
|
"@rollup/plugin-json": "^6.1.0",
|
|
44
47
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
45
48
|
"@sveltejs/vite-plugin-svelte": "^6.0.0-next.3",
|
|
46
49
|
"@types/node": "^18.19.119",
|
|
47
|
-
"@types/set-cookie-parser": "^2.4.7",
|
|
48
50
|
"rollup": "^4.14.2",
|
|
49
51
|
"typescript": "^5.3.3",
|
|
50
|
-
"vitest": "^
|
|
51
|
-
"@sveltejs/kit": "^2.
|
|
52
|
+
"vitest": "^4.0.0",
|
|
53
|
+
"@sveltejs/kit": "^2.52.2"
|
|
52
54
|
},
|
|
53
55
|
"peerDependencies": {
|
|
54
|
-
"@sveltejs/kit": "^2.
|
|
56
|
+
"@sveltejs/kit": "^2.31.0"
|
|
55
57
|
},
|
|
56
58
|
"scripts": {
|
|
57
59
|
"dev": "rollup -cw",
|
|
@@ -59,7 +61,7 @@
|
|
|
59
61
|
"check": "tsc",
|
|
60
62
|
"lint": "prettier --check .",
|
|
61
63
|
"format": "pnpm lint --write",
|
|
62
|
-
"test": "pnpm test:
|
|
64
|
+
"test": "pnpm test:integration",
|
|
63
65
|
"test:unit": "vitest run",
|
|
64
66
|
"test:integration": "pnpm build && pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test"
|
|
65
67
|
}
|