@sveltejs/adapter-netlify 1.0.0-next.4 → 1.0.0-next.43

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,8 @@
1
+ import './shims-c8fba98f.js';
2
+ import 'node:http';
3
+ import 'node:https';
4
+ import 'node:zlib';
5
+ import 'node:stream';
6
+ import 'node:util';
7
+ import 'node:url';
8
+ import 'net';
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Adapter } from '@sveltejs/kit';
2
+
3
+ declare function plugin(opts?: { split?: boolean }): Adapter;
4
+ export = plugin;
package/index.js CHANGED
@@ -1,65 +1,221 @@
1
- const { existsSync, readFileSync, copyFileSync, writeFileSync, renameSync } = require('fs');
2
- const { resolve } = require('path');
3
- const toml = require('toml');
1
+ import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
2
+ import { join, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import glob from 'tiny-glob/sync.js';
5
+ import esbuild from 'esbuild';
6
+ import toml from '@iarna/toml';
4
7
 
5
- module.exports = function () {
6
- /** @type {import('@sveltejs/kit').Adapter} */
7
- const adapter = {
8
+ /**
9
+ * @typedef {{
10
+ * build?: { publish?: string }
11
+ * functions?: { node_bundler?: 'zisi' | 'esbuild' }
12
+ * } & toml.JsonMap} NetlifyConfig
13
+ */
14
+
15
+ const files = fileURLToPath(new URL('./files', import.meta.url));
16
+
17
+ /** @type {import('.')} */
18
+ export default function ({ split = false } = {}) {
19
+ return {
8
20
  name: '@sveltejs/adapter-netlify',
9
21
 
10
22
  async adapt(builder) {
11
- let netlify_config;
12
-
13
- if (existsSync('netlify.toml')) {
14
- try {
15
- netlify_config = toml.parse(readFileSync('netlify.toml', 'utf-8'));
16
- } catch (err) {
17
- err.message = `Error parsing netlify.toml: ${err.message}`;
18
- throw err;
19
- }
23
+ const netlify_config = get_netlify_config();
24
+
25
+ // "build" is the default publish directory when Netlify detects SvelteKit
26
+ const publish = get_publish_directory(netlify_config, builder) || 'build';
27
+
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');
34
+
35
+ builder.mkdirp('.netlify/functions-internal');
36
+
37
+ builder.log.minor(`Publishing to "${publish}"`);
38
+
39
+ builder.log.minor('Prerendering static pages...');
40
+ await builder.prerender({
41
+ dest: publish
42
+ });
43
+
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
+ const replace = {
54
+ APP: './server/app.js'
55
+ };
56
+
57
+ if (esm) {
58
+ builder.copy(`${files}/esm`, '.netlify', { replace });
20
59
  } else {
21
- // TODO offer to create one?
22
- throw new Error(
23
- 'Missing a netlify.toml file. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration'
24
- );
25
- }
60
+ glob('**/*.js', { cwd: '.netlify/server' }).forEach((file) => {
61
+ const filepath = `.netlify/server/${file}`;
62
+ const input = readFileSync(filepath, 'utf8');
63
+ const output = esbuild.transformSync(input, { format: 'cjs', target: 'node12' }).code;
64
+ writeFileSync(filepath, output);
65
+ });
26
66
 
27
- if (
28
- !netlify_config.build ||
29
- !netlify_config.build.publish ||
30
- !netlify_config.build.functions
31
- ) {
32
- throw new Error(
33
- 'You must specify build.publish and build.functions in netlify.toml. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration'
34
- );
67
+ builder.copy(`${files}/cjs`, '.netlify', { replace });
68
+ writeFileSync(join('.netlify', 'package.json'), JSON.stringify({ type: 'commonjs' }));
35
69
  }
36
70
 
37
- const publish = resolve(netlify_config.build.publish);
38
- const functions = resolve(netlify_config.build.functions);
71
+ if (split) {
72
+ builder.log.minor('Generating serverless functions...');
39
73
 
40
- builder.copy_static_files(publish);
41
- builder.copy_client_files(publish);
42
- builder.copy_server_files(`${functions}/render`);
74
+ builder.createEntries((route) => {
75
+ const parts = [];
43
76
 
44
- // rename app to .mjs
45
- renameSync(`${functions}/render/app.js`, `${functions}/render/app.mjs`);
77
+ for (const segment of route.segments) {
78
+ if (segment.rest) {
79
+ parts.push('*');
80
+ break; // Netlify redirects don't allow anything after a *
81
+ } else if (segment.dynamic) {
82
+ parts.push(`:${parts.length}`);
83
+ } else {
84
+ parts.push(segment.content);
85
+ }
86
+ }
46
87
 
47
- // copy the renderer
48
- copyFileSync(resolve(__dirname, 'files/render.js'), `${functions}/render/handler.mjs`);
88
+ const pattern = `/${parts.join('/')}`;
89
+ const name = parts.join('-').replace(/[:.]/g, '_').replace('*', '__rest') || 'index';
49
90
 
50
- // copy the entry point
51
- copyFileSync(resolve(__dirname, 'files/index.cjs'), `${functions}/render/index.js`);
91
+ return {
92
+ id: pattern,
93
+ filter: (other) => matches(route.segments, other.segments),
94
+ complete: (entry) => {
95
+ const manifest = entry.generateManifest({
96
+ relativePath: '../server',
97
+ format: esm ? 'esm' : 'cjs'
98
+ });
52
99
 
53
- // create _redirects
54
- writeFileSync(`${publish}/_redirects`, '/* /.netlify/functions/render 200');
100
+ const fn = esm
101
+ ? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
102
+ : `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
55
103
 
56
- // prerender
57
- builder.log.info('Prerendering static pages...');
58
- await builder.prerender({
59
- dest: publish
60
- });
104
+ writeFileSync(`.netlify/functions-internal/${name}.js`, fn);
105
+
106
+ redirects.push(`${pattern} /.netlify/functions/${name} 200`);
107
+ }
108
+ };
109
+ });
110
+ } else {
111
+ builder.log.minor('Generating serverless functions...');
112
+
113
+ const manifest = builder.generateManifest({
114
+ relativePath: '../server',
115
+ format: esm ? 'esm' : 'cjs'
116
+ });
117
+
118
+ const fn = esm
119
+ ? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
120
+ : `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
121
+
122
+ writeFileSync('.netlify/functions-internal/render.js', fn);
123
+
124
+ redirects.push('* /.netlify/functions/render 200');
125
+ }
126
+
127
+ builder.log.minor('Copying assets...');
128
+ builder.writeStatic(publish);
129
+ builder.writeClient(publish);
130
+
131
+ builder.log.minor('Writing redirects...');
132
+ const redirect_file = join(publish, '_redirects');
133
+ builder.copy('_redirects', redirect_file);
134
+ appendFileSync(redirect_file, `\n\n${redirects.join('\n')}`);
135
+
136
+ builder.log.minor('Writing custom headers...');
137
+ const headers_file = join(publish, '_headers');
138
+ builder.copy('_headers', headers_file);
139
+ appendFileSync(
140
+ headers_file,
141
+ `\n\n/${builder.appDir}/*\n cache-control: public\n cache-control: immutable\n cache-control: max-age=31536000\n`
142
+ );
61
143
  }
62
144
  };
145
+ }
146
+
147
+ function get_netlify_config() {
148
+ if (!existsSync('netlify.toml')) return null;
149
+
150
+ try {
151
+ return /** @type {NetlifyConfig} */ (toml.parse(readFileSync('netlify.toml', 'utf-8')));
152
+ } catch (err) {
153
+ err.message = `Error parsing netlify.toml: ${err.message}`;
154
+ throw err;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * @param {NetlifyConfig} netlify_config
160
+ * @param {import('@sveltejs/kit').Builder} builder
161
+ **/
162
+ function get_publish_directory(netlify_config, builder) {
163
+ if (netlify_config) {
164
+ if (!netlify_config.build || !netlify_config.build.publish) {
165
+ builder.log.warn('No publish directory specified in netlify.toml, using default');
166
+ return;
167
+ }
168
+
169
+ if (netlify_config.redirects) {
170
+ throw new Error(
171
+ "Redirects are not supported in netlify.toml. Use _redirects instead. For more details consult the readme's troubleshooting section."
172
+ );
173
+ }
174
+ if (resolve(netlify_config.build.publish) === process.cwd()) {
175
+ throw new Error(
176
+ 'The publish directory cannot be set to the site root. Please change it to another value such as "build" in netlify.toml.'
177
+ );
178
+ }
179
+ return netlify_config.build.publish;
180
+ }
181
+
182
+ builder.log.warn(
183
+ 'No netlify.toml found. Using default publish directory. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration for more details '
184
+ );
185
+ }
186
+
187
+ /**
188
+ * @typedef {{ rest: boolean, dynamic: boolean, content: string }} RouteSegment
189
+ */
190
+
191
+ /**
192
+ * @param {RouteSegment[]} a
193
+ * @param {RouteSegment[]} b
194
+ * @returns {boolean}
195
+ */
196
+ function matches(a, b) {
197
+ if (a[0] && b[0]) {
198
+ if (b[0].rest) {
199
+ if (b.length === 1) return true;
200
+
201
+ const next_b = b.slice(1);
202
+
203
+ for (let i = 0; i < a.length; i += 1) {
204
+ if (matches(a.slice(i), next_b)) return true;
205
+ }
206
+
207
+ return false;
208
+ }
209
+
210
+ if (!b[0].dynamic) {
211
+ if (!a[0].dynamic && a[0].content !== b[0].content) return false;
212
+ }
63
213
 
64
- return adapter;
65
- };
214
+ if (a.length === 1 && b.length === 1) return true;
215
+ return matches(a.slice(1), b.slice(1));
216
+ } else if (a[0]) {
217
+ return a.length === 1 && a[0].rest;
218
+ } else {
219
+ return b.length === 1 && b[0].rest;
220
+ }
221
+ }
package/package.json CHANGED
@@ -1,20 +1,45 @@
1
1
  {
2
- "name": "@sveltejs/adapter-netlify",
3
- "version": "1.0.0-next.4",
4
- "main": "index.js",
5
- "files": [
6
- "files"
7
- ],
8
- "scripts": {
9
- "lint": "eslint --ignore-path .gitignore \"**/*.{ts,js,svelte}\" && npm run check-format",
10
- "format": "prettier --write . --config ../../.prettierrc --ignore-path .gitignore",
11
- "check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore"
12
- },
13
- "dependencies": {
14
- "toml": "^3.0.0"
15
- },
16
- "devDependencies": {
17
- "@sveltejs/kit": "1.0.0-next.54",
18
- "typescript": "^4.2.3"
19
- }
20
- }
2
+ "name": "@sveltejs/adapter-netlify",
3
+ "version": "1.0.0-next.43",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/sveltejs/kit",
7
+ "directory": "packages/adapter-netlify"
8
+ },
9
+ "license": "MIT",
10
+ "homepage": "https://kit.svelte.dev",
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./index.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "main": "index.js",
19
+ "types": "index.d.ts",
20
+ "files": [
21
+ "files",
22
+ "index.d.ts"
23
+ ],
24
+ "dependencies": {
25
+ "@iarna/toml": "^2.2.5",
26
+ "esbuild": "^0.13.15",
27
+ "tiny-glob": "^0.2.9"
28
+ },
29
+ "devDependencies": {
30
+ "@netlify/functions": "^0.11.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.241",
35
+ "rimraf": "^3.0.2",
36
+ "rollup": "^2.58.0"
37
+ },
38
+ "scripts": {
39
+ "dev": "rimraf files && rollup -cw",
40
+ "build": "rimraf files && rollup -c",
41
+ "lint": "eslint --ignore-path .gitignore \"**/*.{ts,js,svelte}\" && npm run check-format",
42
+ "format": "npm run check-format -- --write",
43
+ "check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore"
44
+ }
45
+ }
package/CHANGELOG.md DELETED
@@ -1,62 +0,0 @@
1
- # @sveltejs/adapter-netlify
2
-
3
- ## 1.0.0-next.4
4
-
5
- ### Patch Changes
6
-
7
- - 8805c6d: Pass adapters directly to svelte.config.cjs
8
-
9
- ## 1.0.0-next.3
10
-
11
- ### Patch Changes
12
-
13
- - f35a5cd: Change adapter signature
14
-
15
- ## 1.0.0-next.2
16
-
17
- ### Patch Changes
18
-
19
- - 512b8c9: adapter-netlify: Use CJS entrypoint
20
-
21
- ## 1.0.0-next.1
22
-
23
- ### Patch Changes
24
-
25
- - Fix adapters and convert to ES modules
26
-
27
- ## 0.0.13
28
-
29
- ### Patch Changes
30
-
31
- - Add svelte-kit start command
32
-
33
- ## 0.0.12
34
-
35
- ### Patch Changes
36
-
37
- - b475ed4: Overhaul adapter API - fixes #166
38
-
39
- ## 0.0.11
40
-
41
- ### Patch Changes
42
-
43
- - 67eaeea: Move app-utils stuff into subpackages
44
-
45
- ## 0.0.10
46
-
47
- ### Patch Changes
48
-
49
- - Use setup
50
-
51
- ## 0.0.9
52
-
53
- ### Patch Changes
54
-
55
- - 0320208: Rename 'server route' to 'endpoint'
56
- - 5ca907c: Use shared mkdirp helper
57
-
58
- ## 0.0.8
59
-
60
- ### Patch Changes
61
-
62
- - various
package/files/index.cjs DELETED
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- async handler(event) {
3
- const { handler } = await import('./handler.mjs');
4
- return await handler(event);
5
- }
6
- };
package/files/render.js DELETED
@@ -1,44 +0,0 @@
1
- 'use strict';
2
-
3
- import { URLSearchParams } from 'url';
4
- import { render } from './app.mjs'; // eslint-disable-line import/no-unresolved
5
-
6
- export async function handler(event) {
7
- const {
8
- path,
9
- httpMethod,
10
- headers,
11
- queryStringParameters
12
- // body, // TODO pass this to renderer
13
- // isBase64Encoded // TODO is this useful?
14
- } = event;
15
-
16
- const query = new URLSearchParams();
17
- for (const k in queryStringParameters) {
18
- const value = queryStringParameters[k];
19
- value.split(', ').forEach((v) => {
20
- query.append(k, v);
21
- });
22
- }
23
-
24
- const rendered = await render({
25
- method: httpMethod,
26
- headers,
27
- path,
28
- query
29
- });
30
-
31
- if (rendered) {
32
- return {
33
- isBase64Encoded: false,
34
- statusCode: rendered.status,
35
- headers: rendered.headers,
36
- body: rendered.body
37
- };
38
- }
39
-
40
- return {
41
- statusCode: 404,
42
- body: 'Not found'
43
- };
44
- }