forked from sveltejs/kit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
183 lines (149 loc) · 5.4 KB
/
index.js
File metadata and controls
183 lines (149 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import { execSync } from 'node:child_process';
import { adapters } from './adapters.js';
import path from 'node:path';
import fs from 'node:fs';
import process from 'node:process';
/**
* @template T
* @template {keyof T} K
* @typedef {Partial<Omit<T, K>> & Required<Pick<T, K>>} PartialExcept
*/
/**
* We use a custom `Builder` type here to support the minimum version of SvelteKit.
* @typedef {PartialExcept<import('@sveltejs/kit').Builder, 'log' | 'rimraf' | 'mkdirp' | 'config' | 'prerendered' | 'routes' | 'createEntries' | 'generateFallback' | 'generateEnvModule' | 'generateManifest' | 'getBuildDirectory' | 'getClientDirectory' | 'getServerDirectory' | 'getAppPath' | 'writeClient' | 'writePrerendered' | 'writePrerendered' | 'writeServer' | 'copy' | 'compress'>} Builder2_0_0
*/
/** @type {Record<string, (name: string, version: string) => string>} */
const commands = {
npm: (name, version) => `npm install -D ${name}@${version}`,
pnpm: (name, version) => `pnpm add -D ${name}@${version}`,
yarn: (name, version) => `yarn add -D ${name}@${version}`,
bun: (name, version) => `bun add -D ${name}@${version}`,
deno: (name, version) => `deno install -D npm:${name}@${version}`
};
function detect_lockfile() {
let dir = process.cwd();
/** @param {string} file */
const exists = (file) => fs.existsSync(path.join(dir, file));
do {
if (exists('pnpm-lock.yaml')) return 'pnpm';
if (exists('yarn.lock')) return 'yarn';
if (exists('package-lock.json')) return 'npm';
if (exists('bun.lockb') || exists('bun.lock')) return 'bun';
if (exists('deno.lock')) return 'deno';
} while (dir !== (dir = path.dirname(dir)));
return 'npm';
}
function detect_package_manager() {
const manager = detect_lockfile();
try {
execSync(`${manager} --version`);
return manager;
} catch {
return 'npm';
}
}
/**
* Resolves a peer dependency relative to the current CWD. Duplicated with `packages/kit`
* @param {string} dependency
*/
function resolve_peer(dependency) {
let [name, ...parts] = dependency.split('/');
if (name[0] === '@') name += `/${parts.shift()}`;
let dir = process.cwd();
while (!fs.existsSync(`${dir}/node_modules/${name}/package.json`)) {
if (dir === (dir = path.dirname(dir))) {
throw new Error(
`Could not resolve peer dependency "${name}" relative to your project — please install it and try again.`
);
}
}
const pkg_dir = `${dir}/node_modules/${name}`;
const pkg = JSON.parse(fs.readFileSync(`${pkg_dir}/package.json`, 'utf-8'));
const subpackage = ['.', ...parts].join('/');
let exported = pkg.exports[subpackage];
while (typeof exported !== 'string') {
if (!exported) {
throw new Error(`Could not find valid "${subpackage}" export in ${name}/package.json`);
}
exported = exported['import'] ?? exported['default'];
}
return path.resolve(pkg_dir, exported);
}
/** @typedef {import('@sveltejs/kit').Adapter} Adapter */
/**
* @returns {Promise<Adapter | undefined>} The corresponding adapter for the current environment if found otherwise undefined
*/
async function get_adapter() {
const match = adapters.find((candidate) => candidate.test());
if (!match) return;
/** @type {string} */
let resolved;
try {
resolved = resolve_peer(match.module);
} catch {
const package_manager = detect_package_manager();
const command = commands[package_manager](match.module, match.version);
try {
console.log(`Installing ${match.module}...`);
execSync(command, {
stdio: 'inherit',
env: {
...process.env,
NODE_ENV: undefined
}
});
resolved = resolve_peer(match.module);
console.log(`Successfully installed ${match.module}.`);
console.warn(
`\nIf you plan on staying on this deployment platform, consider replacing @sveltejs/adapter-auto with ${match.module}. This will give you faster and more robust installs, and more control over deployment configuration.\n`
);
} catch (e) {
throw new Error(
`Could not install ${match.module}. Please install it yourself by adding it to your package.json's devDependencies and try building your project again.`,
{ cause: e }
);
}
}
/** @type {{ default: () => Adapter }} */
const module = await import(resolved);
const adapter = module.default();
return {
...adapter,
adapt: (builder) => {
builder.log.info(`Detected environment: ${match.name}. Using ${match.module}`);
return adapter.adapt(builder);
}
};
}
/** @type {() => Adapter} */
export default () => ({
name: '@sveltejs/adapter-auto',
/** @param {Builder2_0_0} builder */
adapt: async (builder) => {
const adapter = await get_adapter();
if (adapter) return adapter.adapt(/** @type {import('@sveltejs/kit').Builder} */ (builder));
builder.log.warn(
'Could not detect a supported production environment. See https://svelte.dev/docs/kit/adapters to learn how to configure your app to run on the platform of your choosing'
);
},
supports: {
read: () => {
supports_error(
'The read function imported from $app/server only works in certain environments'
);
},
instrumentation: () => {
supports_error('`instrumentation.server.js` only works in certain environments');
}
}
});
/**
* @param {string} message
* @returns {never}
* @throws {Error}
*/
function supports_error(message) {
throw new Error(
`${message}. Since you're using @sveltejs/adapter-auto, SvelteKit cannot determine whether it will work when your app is deployed. Please replace it with an adapter tailored to your target environment.`
);
}