|
| 1 | +import { defineAddon, defineAddonOptions } from '@sveltejs/cli-core'; |
| 2 | +import { exports, functions, imports, object, type AstTypes } from '@sveltejs/cli-core/js'; |
| 3 | +import { parseJson, parseScript } from '@sveltejs/cli-core/parsers'; |
| 4 | + |
| 5 | +type Adapter = { |
| 6 | + id: string; |
| 7 | + package: string; |
| 8 | + version: string; |
| 9 | +}; |
| 10 | + |
| 11 | +const adapters: Adapter[] = [ |
| 12 | + { id: 'node', package: '@sveltejs/adapter-node', version: '^5.2.9' }, |
| 13 | + { id: 'static', package: '@sveltejs/adapter-static', version: '^3.0.6' }, |
| 14 | + { id: 'vercel', package: '@sveltejs/adapter-vercel', version: '^5.5.0' }, |
| 15 | + { id: 'cloudflare-pages', package: '@sveltejs/adapter-cloudflare', version: '^4.8.0' }, |
| 16 | + { id: 'cloudflare-workers', package: '@sveltejs/adapter-cloudflare-workers', version: '^2.6.0' }, |
| 17 | + { id: 'netlify', package: '@sveltejs/adapter-netlify', version: '^4.4.0' } |
| 18 | +]; |
| 19 | + |
| 20 | +const options = defineAddonOptions({ |
| 21 | + adapter: { |
| 22 | + type: 'select', |
| 23 | + question: 'Which SvelteKit adapter would you like to use?', |
| 24 | + options: adapters.map((p) => ({ value: p.id, label: p.id, hint: p.package })), |
| 25 | + default: 'node' |
| 26 | + } |
| 27 | +}); |
| 28 | + |
| 29 | +export default defineAddon({ |
| 30 | + id: 'sveltekit-adapter', |
| 31 | + alias: 'adapter', |
| 32 | + shortDescription: 'deployment', |
| 33 | + homepage: 'https://svelte.dev/docs/kit/adapters', |
| 34 | + options, |
| 35 | + setup: ({ kit, unsupported }) => { |
| 36 | + if (!kit) unsupported('Requires SvelteKit'); |
| 37 | + }, |
| 38 | + run: ({ sv, options }) => { |
| 39 | + const adapter = adapters.find((a) => a.id === options.adapter)!; |
| 40 | + |
| 41 | + // removes previously installed adapters |
| 42 | + sv.file('package.json', (content) => { |
| 43 | + const { data, generateCode } = parseJson(content); |
| 44 | + const devDeps = data['devDependencies']; |
| 45 | + |
| 46 | + for (const pkg of Object.keys(devDeps)) { |
| 47 | + if (pkg.startsWith('@sveltejs/adapter-')) { |
| 48 | + delete devDeps[pkg]; |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + return generateCode(); |
| 53 | + }); |
| 54 | + |
| 55 | + sv.devDependency(adapter.package, adapter.version); |
| 56 | + |
| 57 | + sv.file('svelte.config.js', (content) => { |
| 58 | + const { ast, generateCode } = parseScript(content); |
| 59 | + |
| 60 | + // finds any existing adapter's import declaration |
| 61 | + const importDecls = ast.body.filter((n) => n.type === 'ImportDeclaration'); |
| 62 | + const adapterImportDecl = importDecls.find( |
| 63 | + (importDecl) => |
| 64 | + typeof importDecl.source.value === 'string' && |
| 65 | + importDecl.source.value.startsWith('@sveltejs/adapter-') && |
| 66 | + importDecl.importKind === 'value' |
| 67 | + ); |
| 68 | + |
| 69 | + let adapterName = 'adapter'; |
| 70 | + if (adapterImportDecl) { |
| 71 | + // replaces the import's source with the new adapter |
| 72 | + adapterImportDecl.source.value = adapter.package; |
| 73 | + adapterName = adapterImportDecl.specifiers?.find((s) => s.type === 'ImportDefaultSpecifier') |
| 74 | + ?.local?.name as string; |
| 75 | + } else { |
| 76 | + imports.addDefault(ast, adapter.package, adapterName); |
| 77 | + } |
| 78 | + |
| 79 | + const { value: config } = exports.defaultExport(ast, object.createEmpty()); |
| 80 | + const kitConfig = config.properties.find( |
| 81 | + (p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' && p.key.name === 'kit' |
| 82 | + ) as AstTypes.ObjectProperty | undefined; |
| 83 | + |
| 84 | + if (kitConfig && kitConfig.value.type === 'ObjectExpression') { |
| 85 | + // only overrides the `adapter` property so we can reset it's args |
| 86 | + object.overrideProperties(kitConfig.value, { |
| 87 | + adapter: functions.callByIdentifier(adapterName, []) |
| 88 | + }); |
| 89 | + } else { |
| 90 | + // creates the `kit` property when absent |
| 91 | + object.properties(config, { |
| 92 | + kit: object.create({ |
| 93 | + adapter: functions.callByIdentifier(adapterName, []) |
| 94 | + }) |
| 95 | + }); |
| 96 | + } |
| 97 | + |
| 98 | + return generateCode(); |
| 99 | + }); |
| 100 | + } |
| 101 | +}); |
0 commit comments