Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

typescript-svelte-plugin

Package Overview
Dependencies
Maintainers
3
Versions
60
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typescript-svelte-plugin - npm Package Compare versions

Comparing version
0.3.0
to
0.3.1
+10
dist/src/config-manager.d.ts
export interface Configuration {
enable: boolean;
}
export declare class ConfigManager {
private emitter;
private config;
onConfigurationChanged(listener: (config: Configuration) => void): void;
updateConfigFromPluginConfig(config: Configuration): void;
getConfig(): Configuration;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigManager = void 0;
const events_1 = require("events");
const configurationEventName = 'configuration-changed';
class ConfigManager {
constructor() {
this.emitter = new events_1.EventEmitter();
this.config = {
enable: true
};
}
onConfigurationChanged(listener) {
this.emitter.on(configurationEventName, listener);
}
updateConfigFromPluginConfig(config) {
this.config = {
...this.config,
...config
};
this.emitter.emit(configurationEventName, config);
}
getConfig() {
return this.config;
}
}
exports.ConfigManager = ConfigManager;
import type ts from 'typescript/lib/tsserverlibrary';
import { ConfigManager } from './config-manager';
import { SvelteSnapshotManager } from './svelte-snapshots';
export interface TsFilesSpec {
include?: readonly string[];
exclude?: readonly string[];
}
export declare class ProjectSvelteFilesManager {
private readonly typescript;
private readonly project;
private readonly serverHost;
private readonly snapshotManager;
private parsedCommandLine;
private files;
private directoryWatchers;
private static instances;
static getInstance(projectName: string): ProjectSvelteFilesManager | undefined;
constructor(typescript: typeof ts, project: ts.server.Project, serverHost: ts.server.ServerHost, snapshotManager: SvelteSnapshotManager, parsedCommandLine: ts.ParsedCommandLine, configManager: ConfigManager);
updateProjectConfig(serviceHost: ts.LanguageServiceHost): void;
getFiles(): string[];
/**
* Create directory watcher for include and exclude
* The watcher in tsserver doesn't support svelte file
* It won't add new created svelte file to root
*/
private setupWatchers;
private watcherCallback;
private updateProjectSvelteFiles;
private addFileToProject;
private readProjectSvelteFilesFromFs;
private onConfigChanged;
private removeFileFromProject;
private disposeWatchersAndFiles;
dispose(): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectSvelteFilesManager = void 0;
const utils_1 = require("./utils");
class ProjectSvelteFilesManager {
constructor(typescript, project, serverHost, snapshotManager, parsedCommandLine, configManager) {
this.typescript = typescript;
this.project = project;
this.serverHost = serverHost;
this.snapshotManager = snapshotManager;
this.parsedCommandLine = parsedCommandLine;
this.files = new Set();
this.directoryWatchers = new Set();
if (configManager.getConfig().enable) {
this.setupWatchers();
this.updateProjectSvelteFiles();
}
configManager.onConfigurationChanged(this.onConfigChanged.bind(this));
ProjectSvelteFilesManager.instances.set(project.getProjectName(), this);
}
static getInstance(projectName) {
return this.instances.get(projectName);
}
updateProjectConfig(serviceHost) {
var _a;
const parsedCommandLine = (_a = serviceHost.getParsedCommandLine) === null || _a === void 0 ? void 0 : _a.call(serviceHost, (0, utils_1.getConfigPathForProject)(this.project));
if (!parsedCommandLine) {
return;
}
this.disposeWatchersAndFiles();
this.parsedCommandLine = parsedCommandLine;
this.setupWatchers();
this.updateProjectSvelteFiles();
}
getFiles() {
return Array.from(this.files);
}
/**
* Create directory watcher for include and exclude
* The watcher in tsserver doesn't support svelte file
* It won't add new created svelte file to root
*/
setupWatchers() {
for (const directory in this.parsedCommandLine.wildcardDirectories) {
if (!Object.prototype.hasOwnProperty.call(this.parsedCommandLine.wildcardDirectories, directory)) {
continue;
}
const watchDirectoryFlags = this.parsedCommandLine.wildcardDirectories[directory];
const watcher = this.serverHost.watchDirectory(directory, this.watcherCallback.bind(this), watchDirectoryFlags === this.typescript.WatchDirectoryFlags.Recursive, this.parsedCommandLine.watchOptions);
this.directoryWatchers.add(watcher);
}
}
watcherCallback(fileName) {
if (!(0, utils_1.isSvelteFilePath)(fileName)) {
return;
}
// We can't just add the file to the project directly, because
// - the casing of fileName is different
// - we don't know whether the file was added or deleted
this.updateProjectSvelteFiles();
}
updateProjectSvelteFiles() {
const fileNamesAfter = this.readProjectSvelteFilesFromFs();
const removedFiles = new Set(...this.files);
const newFiles = fileNamesAfter.filter((fileName) => {
const has = this.files.has(fileName);
if (has) {
removedFiles.delete(fileName);
}
return !has;
});
for (const newFile of newFiles) {
this.addFileToProject(newFile);
this.files.add(newFile);
}
for (const removedFile of removedFiles) {
this.removeFileFromProject(removedFile, false);
this.files.delete(removedFile);
}
}
addFileToProject(newFile) {
this.snapshotManager.create(newFile);
const snapshot = this.project.projectService.getScriptInfo(newFile);
if (snapshot) {
this.project.addRoot(snapshot);
}
}
readProjectSvelteFilesFromFs() {
const fileSpec = this.parsedCommandLine.raw;
const { include, exclude } = fileSpec;
if ((include === null || include === void 0 ? void 0 : include.length) === 0) {
return [];
}
return this.typescript.sys
.readDirectory(this.project.getCurrentDirectory() || process.cwd(), ['.svelte'], exclude, include)
.map(this.typescript.server.toNormalizedPath);
}
onConfigChanged(config) {
this.disposeWatchersAndFiles();
if (config.enable) {
this.setupWatchers();
this.updateProjectSvelteFiles();
}
}
removeFileFromProject(file, exists = true) {
const info = this.project.getScriptInfo(file);
if (info) {
this.project.removeFile(info, exists, true);
}
}
disposeWatchersAndFiles() {
this.directoryWatchers.forEach((watcher) => watcher.close());
this.directoryWatchers.clear();
this.files.forEach((file) => this.removeFileFromProject(file));
this.files.clear();
}
dispose() {
this.disposeWatchersAndFiles();
ProjectSvelteFilesManager.instances.delete(this.project.getProjectName());
}
}
exports.ProjectSvelteFilesManager = ProjectSvelteFilesManager;
ProjectSvelteFilesManager.instances = new Map();
+1
-4
import type ts from 'typescript/lib/tsserverlibrary';
declare function init(modules: {
typescript: typeof ts;
}): {
create: (info: ts.server.PluginCreateInfo) => ts.LanguageService;
getExternalFiles: (project: ts.server.ConfiguredProject) => string[];
};
}): ts.server.PluginModule;
export = init;
+56
-10

@@ -7,3 +7,7 @@ "use strict";

const svelte_snapshots_1 = require("./svelte-snapshots");
const config_manager_1 = require("./config-manager");
const project_svelte_files_1 = require("./project-svelte-files");
const utils_1 = require("./utils");
function init(modules) {
const configManager = new config_manager_1.ConfigManager();
function create(info) {

@@ -16,13 +20,43 @@ var _a, _b, _c, _d;

}
logger.log('Starting Svelte plugin');
// If someone knows a better/more performant way to get svelteOptions,
// please tell us :)
const svelteOptions = ((_d = (_c = (_b = (_a = info.languageServiceHost).getParsedCommandLine) === null || _b === void 0 ? void 0 : _b.call(_a, info.project.getCompilerOptions().configFilePath)) === null || _c === void 0 ? void 0 : _c.raw) === null || _d === void 0 ? void 0 : _d.svelteOptions) || { namespace: 'svelteHTML' };
if ((0, language_service_1.isPatched)(info.languageService)) {
logger.log('Already patched. Checking tsconfig updates.');
(_a = project_svelte_files_1.ProjectSvelteFilesManager.getInstance(info.project.getProjectName())) === null || _a === void 0 ? void 0 : _a.updateProjectConfig(info.languageServiceHost);
return info.languageService;
}
configManager.updateConfigFromPluginConfig(info.config);
if (configManager.getConfig().enable) {
logger.log('Starting Svelte plugin');
}
else {
logger.log('Svelte plugin disabled');
logger.log(info.config);
}
// This call the ConfiguredProject.getParsedCommandLine
// where it'll try to load the cached version of the parsedCommandLine
const parsedCommandLine = (_c = (_b = info.languageServiceHost).getParsedCommandLine) === null || _c === void 0 ? void 0 : _c.call(_b, (0, utils_1.getConfigPathForProject)(info.project));
const svelteOptions = ((_d = parsedCommandLine === null || parsedCommandLine === void 0 ? void 0 : parsedCommandLine.raw) === null || _d === void 0 ? void 0 : _d.svelteOptions) || { namespace: 'svelteHTML' };
logger.log('svelteOptions:', svelteOptions);
const snapshotManager = new svelte_snapshots_1.SvelteSnapshotManager(modules.typescript, info.project.projectService, svelteOptions, logger);
(0, module_loader_1.patchModuleLoader)(logger, snapshotManager, modules.typescript, info.languageServiceHost, info.project);
return (0, language_service_1.decorateLanguageService)(info.languageService, snapshotManager, logger);
logger.debug(parsedCommandLine === null || parsedCommandLine === void 0 ? void 0 : parsedCommandLine.wildcardDirectories);
const snapshotManager = new svelte_snapshots_1.SvelteSnapshotManager(modules.typescript, info.project.projectService, svelteOptions, logger, configManager);
const projectSvelteFilesManager = parsedCommandLine
? new project_svelte_files_1.ProjectSvelteFilesManager(modules.typescript, info.project, info.serverHost, snapshotManager, parsedCommandLine, configManager)
: undefined;
(0, module_loader_1.patchModuleLoader)(logger, snapshotManager, modules.typescript, info.languageServiceHost, info.project, configManager);
configManager.onConfigurationChanged(() => {
// enabling/disabling the plugin means TS has to recompute stuff
info.languageService.cleanupSemanticCache();
info.project.markAsDirty();
// updateGraph checks for new root files
// if there's no tsconfig there isn't root files to check
if (projectSvelteFilesManager) {
info.project.updateGraph();
}
});
return decorateLanguageServiceDispose((0, language_service_1.decorateLanguageService)(info.languageService, snapshotManager, logger, configManager), projectSvelteFilesManager !== null && projectSvelteFilesManager !== void 0 ? projectSvelteFilesManager : {
dispose() { }
});
}
function getExternalFiles(project) {
if (!isSvelteProject(project.getCompilerOptions())) {
var _a, _b;
if (!isSvelteProject(project.getCompilerOptions()) || !configManager.getConfig().enable) {
return [];

@@ -37,3 +71,4 @@ }

].map((f) => modules.typescript.sys.resolvePath((0, path_1.resolve)(svelteTsPath, f)));
return svelteTsxFiles;
// let ts know project svelte files to do its optimization
return svelteTsxFiles.concat((_b = (_a = project_svelte_files_1.ProjectSvelteFilesManager.getInstance(project.getProjectName())) === null || _a === void 0 ? void 0 : _a.getFiles()) !== null && _b !== void 0 ? _b : []);
}

@@ -52,4 +87,15 @@ function isSvelteProject(compilerOptions) {

}
return { create, getExternalFiles };
function onConfigurationChanged(config) {
configManager.updateConfigFromPluginConfig(config);
}
function decorateLanguageServiceDispose(languageService, disposable) {
const dispose = languageService.dispose;
languageService.dispose = () => {
disposable.dispose();
dispose();
};
return languageService;
}
return { create, getExternalFiles, onConfigurationChanged };
}
module.exports = init;

@@ -30,3 +30,12 @@ "use strict";

const details = getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
if (details || !(0, utils_1.isSvelteFilePath)(source || '')) {
if (details) {
if ((0, utils_1.isSvelteFilePath)(source || '')) {
logger.debug('TS found Svelte Component import completion details');
return (0, utils_1.replaceDeep)(details, componentPostfix, '');
}
else {
return details;
}
}
if (!(0, utils_1.isSvelteFilePath)(source || '')) {
return details;

@@ -33,0 +42,0 @@ }

import type ts from 'typescript/lib/tsserverlibrary';
import { ConfigManager } from '../config-manager';
import { Logger } from '../logger';
import { SvelteSnapshotManager } from '../svelte-snapshots';
export declare function decorateLanguageService(ls: ts.LanguageService, snapshotManager: SvelteSnapshotManager, logger: Logger): ts.LanguageService;
export declare function isPatched(ls: ts.LanguageService): boolean;
export declare function decorateLanguageService(ls: ts.LanguageService, snapshotManager: SvelteSnapshotManager, logger: Logger, configManager: ConfigManager): ts.LanguageService;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decorateLanguageService = void 0;
exports.decorateLanguageService = exports.isPatched = void 0;
const utils_1 = require("../utils");

@@ -11,3 +11,16 @@ const completions_1 = require("./completions");

const rename_1 = require("./rename");
function decorateLanguageService(ls, snapshotManager, logger) {
const sveltePluginPatchSymbol = Symbol('sveltePluginPatchSymbol');
function isPatched(ls) {
return ls[sveltePluginPatchSymbol] === true;
}
exports.isPatched = isPatched;
function decorateLanguageService(ls, snapshotManager, logger, configManager) {
// Decorate using a proxy so we can dynamically enable/disable method
// patches depending on the enabled state of our config
const proxy = new Proxy(ls, createProxyHandler(configManager));
decorateLanguageServiceInner(proxy, snapshotManager, logger);
return proxy;
}
exports.decorateLanguageService = decorateLanguageService;
function decorateLanguageServiceInner(ls, snapshotManager, logger) {
patchLineColumnOffset(ls, snapshotManager);

@@ -22,3 +35,22 @@ (0, rename_1.decorateRename)(ls, snapshotManager, logger);

}
exports.decorateLanguageService = decorateLanguageService;
function createProxyHandler(configManager) {
const decorated = {};
return {
get(target, p) {
var _a;
// always return patch symbol whether the plugin is enabled or not
if (p === sveltePluginPatchSymbol) {
return true;
}
if (!configManager.getConfig().enable || p === 'dispose') {
return target[p];
}
return ((_a = decorated[p]) !== null && _a !== void 0 ? _a : target[p]);
},
set(_, p, value) {
decorated[p] = value;
return true;
}
};
}
function patchLineColumnOffset(ls, snapshotManager) {

@@ -25,0 +57,0 @@ if (!ls.toLineColumnOffset) {

import type ts from 'typescript/lib/tsserverlibrary';
import { ConfigManager } from './config-manager';
import { Logger } from './logger';

@@ -13,2 +14,2 @@ import { SvelteSnapshotManager } from './svelte-snapshots';

*/
export declare function patchModuleLoader(logger: Logger, snapshotManager: SvelteSnapshotManager, typescript: typeof ts, lsHost: ts.LanguageServiceHost, project: ts.server.Project): void;
export declare function patchModuleLoader(logger: Logger, snapshotManager: SvelteSnapshotManager, typescript: typeof ts, lsHost: ts.LanguageServiceHost, project: ts.server.Project, configManager: ConfigManager): void;

@@ -39,2 +39,5 @@ "use strict";

}
clear() {
this.cache.clear();
}
getKey(moduleName, containingFile) {

@@ -53,3 +56,3 @@ return containingFile + ':::' + (0, utils_1.ensureRealSvelteFilePath)(moduleName);

*/
function patchModuleLoader(logger, snapshotManager, typescript, lsHost, project) {
function patchModuleLoader(logger, snapshotManager, typescript, lsHost, project, configManager) {
var _a;

@@ -66,2 +69,5 @@ const svelteSys = (0, svelte_sys_1.createSvelteSys)(logger);

};
configManager.onConfigurationChanged(() => {
moduleCache.clear();
});
function resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions) {

@@ -74,2 +80,5 @@ logger.log('Resolving modules names for ' + containingFile);

const resolved = (origResolveModuleNames === null || origResolveModuleNames === void 0 ? void 0 : origResolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions)) || Array.from(Array(moduleNames.length));
if (!configManager.getConfig().enable) {
return resolved;
}
return resolved.map((moduleName, idx) => {

@@ -76,0 +85,0 @@ const fileName = moduleNames[idx];

import type ts from 'typescript/lib/tsserverlibrary';
import { ConfigManager } from './config-manager';
import { Logger } from './logger';

@@ -41,6 +42,7 @@ import { SourceMapper } from './source-mapper';

private logger;
private configManager;
private snapshots;
constructor(typescript: typeof ts, projectService: ts.server.ProjectService, svelteOptions: {
namespace: string;
}, logger: Logger);
}, logger: Logger, configManager: ConfigManager);
get(fileName: string): SvelteSnapshot | undefined;

@@ -47,0 +49,0 @@ create(fileName: string): SvelteSnapshot | undefined;

@@ -192,3 +192,3 @@ "use strict";

class SvelteSnapshotManager {
constructor(typescript, projectService, svelteOptions, logger) {
constructor(typescript, projectService, svelteOptions, logger, configManager) {
this.typescript = typescript;

@@ -198,2 +198,3 @@ this.projectService = projectService;

this.logger = logger;
this.configManager = configManager;
this.snapshots = new Map();

@@ -233,3 +234,3 @@ this.patchProjectServiceReadFile();

this.projectService.host.readFile = (path) => {
if ((0, utils_1.isSvelteFilePath)(path)) {
if ((0, utils_1.isSvelteFilePath)(path) && this.configManager.getConfig().enable) {
this.logger.debug('Read Svelte file:', path);

@@ -256,4 +257,7 @@ const svelteCode = readFile(path) || '';

catch (e) {
this.logger.log('Error loading Svelte file:', path);
this.logger.log('Error loading Svelte file:', path, ' Using fallback.');
this.logger.debug('Error:', e);
// Return something either way, else "X is not a module" errors will appear
// in the TS files that use this file.
return 'export default class extends Svelte2TsxComponent<any,any,any> {}';
}

@@ -260,0 +264,0 @@ }

@@ -0,1 +1,2 @@

import type ts from 'typescript/lib/tsserverlibrary';
export declare function isSvelteFilePath(filePath: string): boolean;

@@ -20,1 +21,2 @@ export declare function isVirtualSvelteFilePath(filePath: string): boolean;

export declare function replaceDeep<T extends Record<string, any>>(obj: T, searchStr: string | RegExp, replacementStr: string): T;
export declare function getConfigPathForProject(project: ts.server.Project): ts.server.NormalizedPath;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.replaceDeep = exports.isNoTextSpanInGeneratedCode = exports.isInGeneratedCode = exports.isNotNullOrUndefined = exports.ensureRealSvelteFilePath = exports.toRealSvelteFilePath = exports.isVirtualSvelteFilePath = exports.isSvelteFilePath = void 0;
exports.getConfigPathForProject = exports.replaceDeep = exports.isNoTextSpanInGeneratedCode = exports.isInGeneratedCode = exports.isNotNullOrUndefined = exports.ensureRealSvelteFilePath = exports.toRealSvelteFilePath = exports.isVirtualSvelteFilePath = exports.isSvelteFilePath = void 0;
function isSvelteFilePath(filePath) {

@@ -66,1 +66,6 @@ return filePath.endsWith('.svelte');

exports.replaceDeep = replaceDeep;
function getConfigPathForProject(project) {
var _a;
return ((_a = project.canonicalConfigFilePath) !== null && _a !== void 0 ? _a : project.getCompilerOptions().configFilePath);
}
exports.getConfigPathForProject = getConfigPathForProject;
{
"name": "typescript-svelte-plugin",
"version": "0.3.0",
"version": "0.3.1",
"description": "A TypeScript Plugin providing Svelte intellisense",

@@ -5,0 +5,0 @@ "main": "dist/src/index.js",