Skip to content

Commit e3e6dbc

Browse files
committed
feat(sveltekit): Add SvelteKit menu option and SDK installation
1 parent 1bdd516 commit e3e6dbc

7 files changed

Lines changed: 133 additions & 14 deletions

File tree

lib/Constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export enum Integration {
44
cordova = 'cordova',
55
electron = 'electron',
66
nextjs = 'nextjs',
7+
sveltekit = 'sveltekit',
78
}
89

910
/** Key value should be the same here */
@@ -39,6 +40,8 @@ export function getIntegrationDescription(type: string): string {
3940
return 'Electron';
4041
case Integration.nextjs:
4142
return 'Next.js';
43+
case Integration.sveltekit:
44+
return 'SvelteKit';
4245
default:
4346
return 'React Native';
4447
}
@@ -54,6 +57,8 @@ export function mapIntegrationToPlatform(type: string): string {
5457
return 'javascript-electron';
5558
case Integration.nextjs:
5659
return 'javascript-nextjs';
60+
case Integration.sveltekit:
61+
return 'javascript-sveltekit';
5762
default:
5863
throw new Error(`Unknown integration ${type}`);
5964
}

lib/Helper/Package.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,20 @@ function fulfillsVersionRange(
5959
: satisfies(cleanedUserVersion, acceptableVersions))
6060
);
6161
}
62+
63+
/**
64+
* Determines if the passed `package.json` object has the passed package installed.
65+
*
66+
* @param appPackage The `package.json` object
67+
* @param packageName The name of the package to check for
68+
*
69+
* @returns `true` if the package is installed, `false` otherwise
70+
*/
71+
export function hasPackageInstalled(
72+
appPackage: Record<string, any>,
73+
packageName: string,
74+
): boolean {
75+
const depsVersion = appPackage.dependencies[packageName];
76+
const devDepsVersion = appPackage.devDependencies[packageName];
77+
return !!depsVersion || !!devDepsVersion;
78+
}

lib/Helper/PackageManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { promisify } from 'util';
66

77
import { green } from './Logging';
88

9-
export function getPackageMangerChoice(): PackageManager | null {
9+
export function getPackageManagerChoice(): PackageManager | null {
1010
if (fs.existsSync(path.join(process.cwd(), Yarn.LOCK_FILE))) {
1111
return new Yarn();
1212
}

lib/Steps/ChooseIntegration.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Cordova } from './Integrations/Cordova';
88
import { Electron } from './Integrations/Electron';
99
import { NextJs } from './Integrations/NextJs';
1010
import { ReactNative } from './Integrations/ReactNative';
11+
import { SvelteKit } from './Integrations/SvelteKit';
1112

1213
let projectPackage: any = {};
1314

@@ -54,6 +55,9 @@ export class ChooseIntegration extends BaseStep {
5455
case Integration.nextjs:
5556
integration = new NextJs(this._argv);
5657
break;
58+
case Integration.sveltekit:
59+
integration = new SvelteKit(this._argv);
60+
break;
5761
default:
5862
integration = new ReactNative(this._argv);
5963
break;

lib/Steps/Integrations/NextJs.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import * as path from 'path';
99
import type { Args } from '../../Constants';
1010
import { debug, green, l, nl, red } from '../../Helper/Logging';
1111
import { mergeConfigFile } from '../../Helper/MergeConfig';
12-
import { checkPackageVersion } from '../../Helper/Package';
13-
import { getPackageMangerChoice } from '../../Helper/PackageManager';
12+
import { checkPackageVersion, hasPackageInstalled } from '../../Helper/Package';
13+
import { getPackageManagerChoice } from '../../Helper/PackageManager';
1414
import type { SentryCliProps } from '../../Helper/SentryCli';
1515
import { SentryCli } from '../../Helper/SentryCli';
1616
import { BaseIntegration } from './BaseIntegration';
@@ -116,8 +116,8 @@ export class NextJs extends BaseIntegration {
116116
true,
117117
);
118118

119-
const packageManager = getPackageMangerChoice();
120-
const hasSdkInstalled = this._hasPackageInstalled('@sentry/nextjs');
119+
const packageManager = getPackageManagerChoice();
120+
const hasSdkInstalled = hasPackageInstalled(appPackage, '@sentry/nextjs');
121121

122122
let hasCompatibleSdkVersion = false;
123123
// if no package but we have nextjs, let's add it if we can
@@ -253,7 +253,7 @@ export class NextJs extends BaseIntegration {
253253
// next.config.template.js used for merging next.config.js , not its own template,
254254
// so it shouldn't have a setTemplate call
255255
const filteredTemplates = templates.filter(
256-
(template) => template !== 'next.config.template.js',
256+
template => template !== 'next.config.template.js',
257257
);
258258
for (const template of filteredTemplates) {
259259
await this._setTemplate(
@@ -343,12 +343,6 @@ export class NextJs extends BaseIntegration {
343343
fs.writeFileSync(targetPath, filledTemplate);
344344
}
345345

346-
private _hasPackageInstalled(packageName: string): boolean {
347-
const depsVersion = _.get(appPackage, ['dependencies', packageName]);
348-
const devDepsVersion = _.get(appPackage, ['devDependencies', packageName]);
349-
return !!depsVersion || !!devDepsVersion;
350-
}
351-
352346
private _spliceInPlace(
353347
arr: Array<any>,
354348
start: number,

lib/Steps/Integrations/ReactNative.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from '../../Helper/File';
1717
import { dim, green, nl, red } from '../../Helper/Logging';
1818
import { checkPackageVersion } from '../../Helper/Package';
19-
import { getPackageMangerChoice } from '../../Helper/PackageManager';
19+
import { getPackageManagerChoice } from '../../Helper/PackageManager';
2020
import { SentryCli } from '../../Helper/SentryCli';
2121
import { MobileProject } from './MobileProject';
2222

@@ -55,7 +55,7 @@ export class ReactNative extends MobileProject {
5555
nl();
5656

5757
let userAnswers: Answers = { continue: true };
58-
const packageManager = getPackageMangerChoice();
58+
const packageManager = getPackageManagerChoice();
5959

6060
const hasCompatibleReactNativeVersion = checkPackageVersion(
6161
this._readAppPackage(),
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { info } from 'console';
2+
import type { Answers } from 'inquirer';
3+
import { prompt } from 'inquirer';
4+
import * as path from 'path';
5+
6+
import type { Args } from '../../Constants';
7+
import { nl } from '../../Helper/Logging';
8+
import { checkPackageVersion, hasPackageInstalled } from '../../Helper/Package';
9+
import { getPackageManagerChoice } from '../../Helper/PackageManager';
10+
import { SentryCli } from '../../Helper/SentryCli';
11+
import { BaseIntegration } from './BaseIntegration';
12+
13+
const SVELTEKIT_SDK_PACKAGE = '@sentry/sveltekit';
14+
const COMPATIBLE_SVELTEKIT_VERSIONS = '>=1.0.0';
15+
const COMPATIBLE_SDK_VERSIONS = '>=7.48.0';
16+
17+
let appPackage: any = {};
18+
19+
try {
20+
appPackage = require(path.join(process.cwd(), 'package.json'));
21+
} catch {
22+
// We don't need to have this
23+
}
24+
25+
export class SvelteKit extends BaseIntegration {
26+
private _sentryCli: SentryCli;
27+
public constructor(protected _argv: Args) {
28+
super(_argv);
29+
this._sentryCli = new SentryCli(this._argv);
30+
}
31+
32+
public async emit(_answers: Answers): Promise<Answers> {
33+
info('Setting up SvelteKit SDK');
34+
35+
// TODO: The actual SDK setup
36+
37+
return {};
38+
}
39+
40+
public async shouldConfigure(_answers: Answers): Promise<Answers> {
41+
if (this._shouldConfigure) {
42+
return this._shouldConfigure;
43+
}
44+
45+
nl();
46+
47+
let userAnswers: Answers = { continue: true };
48+
const hasCompatibleSvelteKitVersion = checkPackageVersion(
49+
appPackage,
50+
'@sveltejs/kit',
51+
COMPATIBLE_SVELTEKIT_VERSIONS,
52+
true,
53+
);
54+
55+
const packageManager = getPackageManagerChoice();
56+
const hasSdkInstalled = hasPackageInstalled(
57+
appPackage,
58+
SVELTEKIT_SDK_PACKAGE,
59+
);
60+
61+
let hasCompatibleSdkVersion = false;
62+
// if no SDK is installed but SvelteKit was detected, let's add the SDK if we can
63+
if (!hasSdkInstalled && packageManager && hasCompatibleSvelteKitVersion) {
64+
await packageManager.installPackage(SVELTEKIT_SDK_PACKAGE);
65+
// can assume it's compatible since we just installed it
66+
hasCompatibleSdkVersion = true;
67+
} else {
68+
// otherwise, let's check the version and spit out the appropriate error
69+
hasCompatibleSdkVersion = checkPackageVersion(
70+
appPackage,
71+
SVELTEKIT_SDK_PACKAGE,
72+
COMPATIBLE_SDK_VERSIONS,
73+
true,
74+
);
75+
}
76+
const hasAllPackagesCompatible =
77+
hasCompatibleSvelteKitVersion && hasCompatibleSdkVersion;
78+
79+
if (!hasAllPackagesCompatible && !this._argv.quiet) {
80+
userAnswers = await prompt({
81+
message:
82+
'There were errors while checking your project config. Do you still want to continue?',
83+
name: 'continue',
84+
default: false,
85+
type: 'confirm',
86+
});
87+
}
88+
89+
nl();
90+
91+
if (!userAnswers['continue']) {
92+
throw new Error('Please install the required dependencies to continue.');
93+
}
94+
95+
this._shouldConfigure = Promise.resolve({ sveltekit: true });
96+
// eslint-disable-next-line @typescript-eslint/unbound-method
97+
return this.shouldConfigure;
98+
}
99+
}

0 commit comments

Comments
 (0)