Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1976ddc
fix: CSpellRPCServer and CSpellRPCClient classes
Jason3S Jan 14, 2026
be0746e
Make sure settings can be transfered.
Jason3S Jan 14, 2026
11ead68
implement worker
Jason3S Jan 14, 2026
b56fec7
get it working
Jason3S Jan 14, 2026
2a25366
fix build
Jason3S Jan 15, 2026
f09efef
Update cspellWorker.ts
Jason3S Jan 15, 2026
33f4cd0
Update cleanValidationIssue.ts
Jason3S Jan 15, 2026
8861200
refactor RPC client / server
Jason3S Jan 15, 2026
334cbc7
more tests
Jason3S Jan 15, 2026
8b83b39
more tests
Jason3S Jan 15, 2026
725bbc4
Update clientServer.test.ts
Jason3S Jan 15, 2026
cb01191
Update packages/cspell-lib/src/lib/util/clone.ts
Jason3S Jan 15, 2026
aae32d2
Update sanitizeSettings.ts
Jason3S Jan 15, 2026
316b56f
Update packages/cspell/src/worker/cspellWorker.ts
Jason3S Jan 15, 2026
9f6da5e
Create a cspell-worker package.
Jason3S Jan 15, 2026
1e085c4
Add a simple server rpc worker.
Jason3S Jan 15, 2026
e3154a9
Add tests
Jason3S Jan 15, 2026
2db4092
Update index.test.ts.snap
Jason3S Jan 16, 2026
87174ca
Update packages/cspell-lib/src/lib/spellCheckFile.ts
Jason3S Jan 16, 2026
d26f509
fix spelliing
Jason3S Jan 16, 2026
98baf8d
fix package dir
Jason3S Jan 16, 2026
7ec62ed
Make sure the object is cloned
Jason3S Jan 16, 2026
0ba2ad5
rename memorizer to memoizer
Jason3S Jan 16, 2026
0f45cc7
Update LanguageSettings.ts
Jason3S Jan 16, 2026
55bcfc1
move cspellRPC out of lib
Jason3S Jan 16, 2026
532670b
fix build
Jason3S Jan 16, 2026
8f3dd14
Apply suggestion from @Jason3S
Jason3S Jan 16, 2026
41d9785
Update cspellWorker.ts
Jason3S Jan 16, 2026
3354c2c
Update index.test.ts
Jason3S Jan 16, 2026
d76c5ae
Update vitest.config.mjs
Jason3S Jan 16, 2026
b832a5f
fix coverage
Jason3S Jan 16, 2026
e5466a6
Update index.test.ts
Jason3S Jan 16, 2026
534dfc1
Use forks when testing worker.
Jason3S Jan 16, 2026
d2ef5b2
Add RPC to the API
Jason3S Jan 16, 2026
36be43f
separate the RPC client and server
Jason3S Jan 16, 2026
450cd6f
Update packages/cspell-lib/src/cspell-rpc/server.ts
Jason3S Jan 16, 2026
47e821b
Update packages/cspell-lib/src/lib/util/memoizeLastCall.ts
Jason3S Jan 16, 2026
13dd126
Update tsdown.config.ts
Jason3S Jan 16, 2026
353b513
Add a listener to the port as soon as possible.
Jason3S Jan 16, 2026
f33ebdb
try waiting before checking the worker.
Jason3S Jan 16, 2026
1360dfd
Merge branch 'main' into dev-worker
Jason3S Jan 16, 2026
6fdc701
Update client.ts
Jason3S Jan 16, 2026
ef6bcb3
Update cspellWorker.test.ts
Jason3S Jan 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,912 changes: 1,070 additions & 842 deletions packages/cspell-lib/api/api.d.ts

Large diffs are not rendered by default.

329 changes: 329 additions & 0 deletions packages/cspell-lib/src/lib/Settings/sanitizeSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
import type {
CSpellSettingsWithSourceTrace,
DictionaryDefinition,
Glob,
ImportFileRef,
LanguageSetting,
OverrideSettings,
RegExpPatternDefinition,
Source,
} from '@cspell/cspell-types';

import type { CSpellSettingsInternal, CSpellSettingsInternalFinalized } from '../Models/CSpellSettingsInternalDef.js';
import type { Handlers } from '../util/clone.js';
import { cloneInto, copy0, copy1, skip } from '../util/clone.js';

type CloneableSettings = CSpellSettingsWithSourceTrace | CSpellSettingsInternal | CSpellSettingsInternalFinalized;

type SettingsKeys = keyof CSpellSettingsWithSourceTrace;

type CSpellSettingsHandlers = Handlers<CSpellSettingsWithSourceTrace>;

/**
* Sanitize settings for export by removing any internal only properties.
*
* @param settings - the input settings
*/
export function cloneSettingsForExport(settings: Readonly<CloneableSettings>): CSpellSettingsWithSourceTrace {
const result: CSpellSettingsWithSourceTrace = {};
const handlers = getHandlers();
cloneInto(settings, result, handlers);
return result;
}

const handlers: CSpellSettingsHandlers = {
$schema: skip,
__importRef: copyImportRefField,
__imports: copyImportsField,
source: copySourceField,

id: skip,
version: skip,

allowCompoundWords: copy1,
cache: skip,
caseSensitive: copy1,
description: skip,
dictionaries: copy1,
dictionaryDefinitions: copyDictionaryDefinitions,
enabled: copy1,
enabledLanguageIds: copy1,
enableFiletypes: copy1,
enabledFileTypes: copy1,
enableGlobDot: copy1,
failFast: copy1,
features: skip,
files: copyGlobsSettingsFields,
flagWords: copy1,
gitignoreRoot: copy1,
globRoot: copy1,
ignorePaths: copyGlobsSettingsFields,
ignoreRegExpList: copy1,
ignoreWords: copy1,
ignoreRandomStrings: copy1,
import: skip,
includeRegExpList: copy1,
language: copy1,
languageId: copy1,
languageSettings: copyLanguageSettings,
loadDefaultConfiguration: copy1,
maxDuplicateProblems: copy1,
maxFileSize: copy1,
maxNumberOfProblems: copy1,
minWordLength: copy1,
minRandomLength: copy1,
name: skip,
noConfigSearch: copy1,
noSuggestDictionaries: copy1,
numSuggestions: copy1,
overrides: copyOverrides,
patterns: copyPatternsField,
pnpFiles: skip,
readonly: skip,
reporters: skip,
showStatus: copy1,
spellCheckDelayMs: copy1,
suggestionNumChanges: copy1,
suggestionsTimeout: copy1,
suggestWords: copy1,
unknownWords: copy1,
useGitignore: copy1,
usePnP: skip,
userWords: copy1,
validateDirectives: copy1,
words: copy1,

// Experimental
parser: skip,
};

function getHandlers(): CSpellSettingsHandlers {
return handlers;
}

function copyImportRefField(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, '__importRef'>,
) {
const ref = src[key];
if (!ref) return;
dst[key] = copyImportFileRef(ref);
}

function copyImportsField(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, '__imports'>,
) {
const imports = src[key];
if (!imports) return;
dst[key] = new Map([...imports.entries()].map(([k, v]) => [k, copyImportFileRef(v)]));
}

function copyImportFileRef(src: ImportFileRef): ImportFileRef {
const ref: ImportFileRef = { filename: src.filename };
copy0(src, ref, 'error');
return ref;
}

function copySourceField(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, 'source'>,
) {
if (!src[key]) return;
dst[key] = copySource(src[key]);
}

function copySource(src: Source): Source {
const source: Source = { name: src.name };
cpy(src, source, 'filename');
return source;
}

function copyGlobsSettingsFields(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, 'ignorePaths' | 'files'>,
) {
const globs = src[key];
if (!globs) return;
dst[key] = copyGlobOrGlobs(globs);
}

function copyGlobsOverrideFields(
src: Readonly<OverrideSettings>,
dst: OverrideSettings,
key: Extract<keyof OverrideSettings, 'filename'>,
) {
const globs = src[key];
if (!globs) return;
dst[key] = copyGlobOrGlobs(globs);
}

function copyGlobOrGlobs(globOrGlobs: Glob[]): Glob[];
function copyGlobOrGlobs(globOrGlobs: Glob): Glob;
function copyGlobOrGlobs(globOrGlobs: Glob | Glob[]): Glob | Glob[];
function copyGlobOrGlobs(globOrGlobs: Glob | Glob[]): Glob | Glob[] {
if (Array.isArray(globOrGlobs)) {
return globOrGlobs.map(copyGlob);
}
return copyGlob(globOrGlobs);
}

function copyGlob(glob: Glob): Glob {
if (typeof glob === 'string') {
return glob;
}
const g: Glob = { glob: glob.glob };
cpy(glob, g, 'root');
return g;
}

function copyDictionaryDefinitions(
src: CloneableSettings,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, 'dictionaryDefinitions'>,
): void {
const defs = src[key];
if (!defs) return;
dst[key] = defs.map(copyDictionaryDefinition);
}

function copyDictionaryDefinition(src: DictionaryDefinition): DictionaryDefinition {
const def: DictionaryDefinition = { name: src.name };
cpy(src, def, 'path');
cpy(src, def, 'type');
cpy(src, def, 'description');
return def;
}

function copyLanguageSettings(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, 'languageSettings'>,
): void {
const langSettings = src[key];
if (!langSettings) return;
dst[key] = langSettings.map((src) => {
const dst: LanguageSetting = { languageId: src.languageId };
copyLanguageSetting(src, dst);
return dst;
});
}

function cpy<T, K extends keyof T>(src: T, dst: T, key: K): void {
const value = src[key];
if (value === undefined) return;
dst[key] = value;
}

const LanguageSettingsHandlers: Handlers<LanguageSetting> = {
id: cpy,
locale: cpy,
local: cpy,
allowCompoundWords: copy1,
caseSensitive: copy1,
description: skip,
dictionaries: copy1,
dictionaryDefinitions: copyDictionaryDefinitions,
enabled: copy1,
flagWords: copy1,
ignoreRegExpList: copy1,
ignoreWords: copy1,
includeRegExpList: copy1,
languageId: copy1,
name: skip,
noSuggestDictionaries: copy1,
patterns: copyPatternsField,
suggestWords: copy1,
unknownWords: copy1,
words: copy1,

// Experimental
parser: skip,
};

function copyLanguageSetting(src: Readonly<LanguageSetting>, dst: LanguageSetting): void {
cloneInto(src, dst, LanguageSettingsHandlers);
}

const RegExpPatternDefinitionHandlers: Handlers<RegExpPatternDefinition> = {
name: cpy,
pattern: copy1,
description: cpy,
};

function copyPatternsField(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, 'patterns'>,
): void {
const patterns = src[key];
if (!patterns) return;
dst[key] = patterns.map((p) => {
const dst = { pattern: p.pattern, name: p.name };
copyRegExpPatternDefinition(p, dst);
return dst;
});
}

function copyRegExpPatternDefinition(src: Readonly<RegExpPatternDefinition>, dst: RegExpPatternDefinition): void {
cloneInto(src, dst, RegExpPatternDefinitionHandlers);
Comment thread
Jason3S marked this conversation as resolved.
}

const OverridesHandlers: Handlers<OverrideSettings> = {
id: copy1,
allowCompoundWords: copy1,
caseSensitive: copy1,
description: copy1,
dictionaries: copy1,
dictionaryDefinitions: copyDictionaryDefinitions,
enabled: copy1,
enabledFileTypes: copy1,
enabledLanguageIds: copy1,
enableFiletypes: copy1,
filename: copyGlobsOverrideFields,
flagWords: copy1,
ignoreRandomStrings: copy1,
ignoreRegExpList: copy1,
ignoreWords: copy1,
includeRegExpList: copy1,
language: copy1,
languageId: copy1,
languageSettings: copyLanguageSettings,
loadDefaultConfiguration: copy1,
maxDuplicateProblems: copy1,
maxFileSize: copy1,
maxNumberOfProblems: copy1,
minRandomLength: copy1,
minWordLength: copy1,
name: skip,
noSuggestDictionaries: copy1,
numSuggestions: copy1,
patterns: copyPatternsField,
pnpFiles: skip,
suggestionNumChanges: copy1,
suggestionsTimeout: copy1,
suggestWords: copy1,
unknownWords: copy1,
usePnP: skip,
words: copy1,

parser: skip,
};

function copyOverrides(
src: Readonly<CloneableSettings>,
dst: CSpellSettingsWithSourceTrace,
key: Extract<SettingsKeys, 'overrides'>,
): void {
const overrides = src[key];
if (!overrides) return;
dst[key] = overrides.map((src) => {
const dst = {} as OverrideSettings;
cloneInto(src, dst, OverridesHandlers);
return dst;
});
}
4 changes: 4 additions & 0 deletions packages/cspell-lib/src/lib/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

exports[`Validate the cspell API > Verify API exports 1`] = `
{
"CSpellRPCClient": [Function],
"CSpellRPCServer": [Function],
"CSpellRPCServerOptions": undefined,
"CompoundWordsMethod": {
"0": "NONE",
"1": "SEPARATE_WORDS",
Expand Down Expand Up @@ -153,6 +156,7 @@ exports[`Validate the cspell API > Verify API exports 1`] = `
"clearCaches": [Function],
"combineTextAndLanguageSettings": [Function],
"constructSettingsForText": [Function],
"createCSpellRPCServer": [Function],
"createConfigLoader": [Function],
"createPerfTimer": [Function],
"createSpellingDictionary": [Function],
Expand Down
Loading
Loading