From 4e4df97bb941182abed041a60f1d6c08d0fc5c25 Mon Sep 17 00:00:00 2001 From: Josh Faigan Date: Mon, 10 Aug 2026 09:28:10 -0400 Subject: [PATCH 1/4] perf(vscode-extension): deep-import LSP types to keep the server out of the client bundle --- .changeset/tiny-cycles-arrive.md | 5 +++++ packages/vscode-extension/src/browser/extension.ts | 3 ++- .../vscode-extension/src/common/ReferencesProvider.ts | 10 ++++++---- .../vscode-extension/src/common/VsCodeFileSystem.ts | 6 +++++- packages/vscode-extension/src/common/commands.ts | 6 +++--- packages/vscode-extension/src/node/extension.ts | 3 ++- 6 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 .changeset/tiny-cycles-arrive.md diff --git a/.changeset/tiny-cycles-arrive.md b/.changeset/tiny-cycles-arrive.md new file mode 100644 index 000000000..f97968030 --- /dev/null +++ b/.changeset/tiny-cycles-arrive.md @@ -0,0 +1,5 @@ +--- +'theme-check-vscode': patch +--- + +Keep the language server out of the client bundle by deep-importing LSP types. diff --git a/packages/vscode-extension/src/browser/extension.ts b/packages/vscode-extension/src/browser/extension.ts index 074c1447b..528c659ed 100644 --- a/packages/vscode-extension/src/browser/extension.ts +++ b/packages/vscode-extension/src/browser/extension.ts @@ -1,5 +1,6 @@ /// -import { FileStat, FileTuple, path } from '@shopify/theme-check-common'; +import * as path from '@shopify/theme-check-common/dist/path'; +import type { FileStat, FileTuple } from '@shopify/theme-check-common/dist/AbstractFileSystem'; import { commands, ExtensionContext, languages, Uri, workspace } from 'vscode'; import { LanguageClient, diff --git a/packages/vscode-extension/src/common/ReferencesProvider.ts b/packages/vscode-extension/src/common/ReferencesProvider.ts index b08930701..bb262cc3f 100644 --- a/packages/vscode-extension/src/common/ReferencesProvider.ts +++ b/packages/vscode-extension/src/common/ReferencesProvider.ts @@ -1,12 +1,14 @@ -import { path } from '@shopify/theme-check-common'; +import * as path from '@shopify/theme-check-common/dist/path'; import { - AugmentedLocation, - AugmentedReference, ThemeGraphDependenciesRequest, ThemeGraphDidUpdateNotification, ThemeGraphReferenceRequest, ThemeGraphRootRequest, -} from '@shopify/theme-language-server-common'; +} from '@shopify/theme-language-server-common/dist/types'; +import type { + AugmentedLocation, + AugmentedReference, +} from '@shopify/theme-language-server-common/dist/types'; import { commands, Event, diff --git a/packages/vscode-extension/src/common/VsCodeFileSystem.ts b/packages/vscode-extension/src/common/VsCodeFileSystem.ts index 4a465e9d9..3d2764421 100644 --- a/packages/vscode-extension/src/common/VsCodeFileSystem.ts +++ b/packages/vscode-extension/src/common/VsCodeFileSystem.ts @@ -1,4 +1,8 @@ -import { AbstractFileSystem, FileTuple, FileStat } from '@shopify/theme-check-common'; +import type { + AbstractFileSystem, + FileStat, + FileTuple, +} from '@shopify/theme-check-common/dist/AbstractFileSystem'; import { Connection } from 'vscode-languageserver'; import { URI } from 'vscode-uri'; diff --git a/packages/vscode-extension/src/common/commands.ts b/packages/vscode-extension/src/common/commands.ts index 12c5f59e7..2674eb430 100644 --- a/packages/vscode-extension/src/common/commands.ts +++ b/packages/vscode-extension/src/common/commands.ts @@ -1,9 +1,9 @@ -import { path } from '@shopify/theme-check-common'; +import * as path from '@shopify/theme-check-common/dist/path'; import { - AugmentedLocation, ThemeGraphDeadCodeRequest, ThemeGraphRootRequest, -} from '@shopify/theme-language-server-common'; +} from '@shopify/theme-language-server-common/dist/types'; +import type { AugmentedLocation } from '@shopify/theme-language-server-common/dist/types'; import { commands, Position, Range, Uri, window, workspace } from 'vscode'; import { BaseLanguageClient } from 'vscode-languageclient'; diff --git a/packages/vscode-extension/src/node/extension.ts b/packages/vscode-extension/src/node/extension.ts index 0bf9b99fc..a1a0c33ba 100644 --- a/packages/vscode-extension/src/node/extension.ts +++ b/packages/vscode-extension/src/node/extension.ts @@ -1,4 +1,5 @@ -import { FileStat, FileTuple, path as pathUtils } from '@shopify/theme-check-common'; +import * as pathUtils from '@shopify/theme-check-common/dist/path'; +import type { FileStat, FileTuple } from '@shopify/theme-check-common/dist/AbstractFileSystem'; import * as path from 'node:path'; import { commands, ExtensionContext, languages, Uri, workspace } from 'vscode'; import { From f3b7ea9fa52b30de8f6ee80e0368b823ce238604 Mon Sep 17 00:00:00 2001 From: Josh Faigan Date: Tue, 11 Aug 2026 10:23:20 -0400 Subject: [PATCH 2/4] refactor(theme-check-common): expose path and LSP types as public subpaths Replace the vscode-extension's `dist/` deep imports with root-level re-export stubs, so consumers get a supported entry point instead of reaching into build output. `@shopify/theme-check-common/path` and `@shopify/theme-language-server-common/types` re-export their `dist` modules. The extension imports values from those subpaths and takes types from the package barrels, keeping the language server out of the client bundle: browser/extension.js is 2,103,681 bytes and node/extension.js is 1,410,426 bytes, versus 6,722,159 and 6,497,684 when the same values come from a barrel. Purely additive. No package.json, tsconfig, or webpack changes, and the barrel imports behave exactly as before. --- .changeset/tiny-cycles-arrive.md | 8 +++++++- packages/theme-check-common/path.d.ts | 1 + packages/theme-check-common/path.js | 1 + packages/theme-language-server-common/types.d.ts | 1 + packages/theme-language-server-common/types.js | 1 + packages/vscode-extension/src/browser/extension.ts | 4 ++-- .../vscode-extension/src/common/ReferencesProvider.ts | 9 +++------ packages/vscode-extension/src/common/VsCodeFileSystem.ts | 6 +----- packages/vscode-extension/src/common/commands.ts | 6 +++--- packages/vscode-extension/src/node/extension.ts | 4 ++-- 10 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 packages/theme-check-common/path.d.ts create mode 100644 packages/theme-check-common/path.js create mode 100644 packages/theme-language-server-common/types.d.ts create mode 100644 packages/theme-language-server-common/types.js diff --git a/.changeset/tiny-cycles-arrive.md b/.changeset/tiny-cycles-arrive.md index f97968030..4a3b3f35a 100644 --- a/.changeset/tiny-cycles-arrive.md +++ b/.changeset/tiny-cycles-arrive.md @@ -1,5 +1,11 @@ --- +'@shopify/theme-language-server-common': minor +'@shopify/theme-check-common': minor 'theme-check-vscode': patch --- -Keep the language server out of the client bundle by deep-importing LSP types. +Add public subpath entry points for path utilities and LSP request types + +`@shopify/theme-check-common/path` and `@shopify/theme-language-server-common/types` are now public entry points. They re-export the same members as the package barrel, but importing them pulls in only that module instead of the whole package. + +The VS Code extension uses them to keep the language server out of the client bundle: `browser/extension.js` is 2.1 MB instead of 6.7 MB, and `node/extension.js` is 1.4 MB instead of 6.5 MB. The barrel imports still work exactly as before. diff --git a/packages/theme-check-common/path.d.ts b/packages/theme-check-common/path.d.ts new file mode 100644 index 000000000..cc2f65808 --- /dev/null +++ b/packages/theme-check-common/path.d.ts @@ -0,0 +1 @@ +export * from './dist/path'; diff --git a/packages/theme-check-common/path.js b/packages/theme-check-common/path.js new file mode 100644 index 000000000..886a4fcad --- /dev/null +++ b/packages/theme-check-common/path.js @@ -0,0 +1 @@ +module.exports = require('./dist/path'); diff --git a/packages/theme-language-server-common/types.d.ts b/packages/theme-language-server-common/types.d.ts new file mode 100644 index 000000000..7236c51a0 --- /dev/null +++ b/packages/theme-language-server-common/types.d.ts @@ -0,0 +1 @@ +export * from './dist/types'; diff --git a/packages/theme-language-server-common/types.js b/packages/theme-language-server-common/types.js new file mode 100644 index 000000000..d94f7183d --- /dev/null +++ b/packages/theme-language-server-common/types.js @@ -0,0 +1 @@ +module.exports = require('./dist/types'); diff --git a/packages/vscode-extension/src/browser/extension.ts b/packages/vscode-extension/src/browser/extension.ts index 528c659ed..ef4479b96 100644 --- a/packages/vscode-extension/src/browser/extension.ts +++ b/packages/vscode-extension/src/browser/extension.ts @@ -1,6 +1,6 @@ /// -import * as path from '@shopify/theme-check-common/dist/path'; -import type { FileStat, FileTuple } from '@shopify/theme-check-common/dist/AbstractFileSystem'; +import * as path from '@shopify/theme-check-common/path'; +import type { FileStat, FileTuple } from '@shopify/theme-check-common'; import { commands, ExtensionContext, languages, Uri, workspace } from 'vscode'; import { LanguageClient, diff --git a/packages/vscode-extension/src/common/ReferencesProvider.ts b/packages/vscode-extension/src/common/ReferencesProvider.ts index bb262cc3f..76bbc9508 100644 --- a/packages/vscode-extension/src/common/ReferencesProvider.ts +++ b/packages/vscode-extension/src/common/ReferencesProvider.ts @@ -1,14 +1,11 @@ -import * as path from '@shopify/theme-check-common/dist/path'; +import * as path from '@shopify/theme-check-common/path'; import { ThemeGraphDependenciesRequest, ThemeGraphDidUpdateNotification, ThemeGraphReferenceRequest, ThemeGraphRootRequest, -} from '@shopify/theme-language-server-common/dist/types'; -import type { - AugmentedLocation, - AugmentedReference, -} from '@shopify/theme-language-server-common/dist/types'; +} from '@shopify/theme-language-server-common/types'; +import type { AugmentedLocation, AugmentedReference } from '@shopify/theme-language-server-common'; import { commands, Event, diff --git a/packages/vscode-extension/src/common/VsCodeFileSystem.ts b/packages/vscode-extension/src/common/VsCodeFileSystem.ts index 3d2764421..e55e73b1f 100644 --- a/packages/vscode-extension/src/common/VsCodeFileSystem.ts +++ b/packages/vscode-extension/src/common/VsCodeFileSystem.ts @@ -1,8 +1,4 @@ -import type { - AbstractFileSystem, - FileStat, - FileTuple, -} from '@shopify/theme-check-common/dist/AbstractFileSystem'; +import type { AbstractFileSystem, FileStat, FileTuple } from '@shopify/theme-check-common'; import { Connection } from 'vscode-languageserver'; import { URI } from 'vscode-uri'; diff --git a/packages/vscode-extension/src/common/commands.ts b/packages/vscode-extension/src/common/commands.ts index 2674eb430..a2469544e 100644 --- a/packages/vscode-extension/src/common/commands.ts +++ b/packages/vscode-extension/src/common/commands.ts @@ -1,9 +1,9 @@ -import * as path from '@shopify/theme-check-common/dist/path'; +import * as path from '@shopify/theme-check-common/path'; import { ThemeGraphDeadCodeRequest, ThemeGraphRootRequest, -} from '@shopify/theme-language-server-common/dist/types'; -import type { AugmentedLocation } from '@shopify/theme-language-server-common/dist/types'; +} from '@shopify/theme-language-server-common/types'; +import type { AugmentedLocation } from '@shopify/theme-language-server-common'; import { commands, Position, Range, Uri, window, workspace } from 'vscode'; import { BaseLanguageClient } from 'vscode-languageclient'; diff --git a/packages/vscode-extension/src/node/extension.ts b/packages/vscode-extension/src/node/extension.ts index a1a0c33ba..bef002b6e 100644 --- a/packages/vscode-extension/src/node/extension.ts +++ b/packages/vscode-extension/src/node/extension.ts @@ -1,5 +1,5 @@ -import * as pathUtils from '@shopify/theme-check-common/dist/path'; -import type { FileStat, FileTuple } from '@shopify/theme-check-common/dist/AbstractFileSystem'; +import * as pathUtils from '@shopify/theme-check-common/path'; +import type { FileStat, FileTuple } from '@shopify/theme-check-common'; import * as path from 'node:path'; import { commands, ExtensionContext, languages, Uri, workspace } from 'vscode'; import { From 7a6e2021ad0939b404df10e77cde4965bf46b77c Mon Sep 17 00:00:00 2001 From: Josh Faigan Date: Fri, 11 Sep 2026 14:10:05 -0400 Subject: [PATCH 3/4] feat(theme-check-common): define public package subpath exports Add curated `exports` + `typesVersions` maps to `@shopify/theme-check-common` (`.`, `./path`, `./test`, `./package.json`) and `@shopify/theme-language-server-common` (`.`, `./types`, `./package.json`), replacing the root `path.*` / `types.*` forwarder files with a single declared public surface. BREAKING CHANGE: deep imports into `dist/` and `src/` no longer resolve. Seven symbols previously reached via `dist/` deep paths are promoted to the `@shopify/theme-check-common` barrel: `getPosition`, `createDisabledChecksModule`, `UNMATCHED_COMMENT_CLOSE_PARSER_ERROR`, `UNMATCHED_RAW_CLOSE_PARSER_ERROR`, `hasRubyAcceptedInertCommentBodyCloser`, `hasJavascriptClosingTagAfter`, and `hasRubyAcceptedRawTagCloserWithMarkup`. In-repo `@shopify/theme-check-common/{src,dist}/test` call sites move to the public `/test` subpath. New `package-exports.spec.ts` in each package locks both the declared subpaths and the removed legacy ones. --- .changeset/tiny-cycles-arrive.md | 47 ++++++++++++++-- packages/theme-check-common/package.json | 25 +++++++++ packages/theme-check-common/path.d.ts | 1 - packages/theme-check-common/path.js | 1 - packages/theme-check-common/src/index.ts | 9 +++ .../src/package-exports.spec.ts | 55 +++++++++++++++++++ .../theme-language-server-common/package.json | 18 ++++++ .../src/diagnostics/runChecks.spec.ts | 2 +- .../src/documents/DocumentManager.spec.ts | 2 +- .../LiquidDocTagHoverProvider.spec.ts | 1 - .../src/package-exports.spec.ts | 35 ++++++++++++ .../handlers/AssetRenameHandler.spec.ts | 2 +- .../handlers/BlockRenameHandler.spec.ts | 2 +- .../handlers/SectionRenameHandler.spec.ts | 2 +- .../handlers/SnippetRenameHandler.spec.ts | 2 +- .../src/server/startServer.spec.ts | 2 +- .../src/tsconfig.json | 1 + .../theme-language-server-common/types.d.ts | 1 - .../theme-language-server-common/types.js | 1 - tsconfig.json | 9 +++ 20 files changed, 201 insertions(+), 17 deletions(-) delete mode 100644 packages/theme-check-common/path.d.ts delete mode 100644 packages/theme-check-common/path.js create mode 100644 packages/theme-check-common/src/package-exports.spec.ts create mode 100644 packages/theme-language-server-common/src/package-exports.spec.ts delete mode 100644 packages/theme-language-server-common/types.d.ts delete mode 100644 packages/theme-language-server-common/types.js diff --git a/.changeset/tiny-cycles-arrive.md b/.changeset/tiny-cycles-arrive.md index 4a3b3f35a..aedb33861 100644 --- a/.changeset/tiny-cycles-arrive.md +++ b/.changeset/tiny-cycles-arrive.md @@ -1,11 +1,48 @@ --- -'@shopify/theme-language-server-common': minor -'@shopify/theme-check-common': minor +'@shopify/theme-language-server-common': major +'@shopify/theme-check-common': major 'theme-check-vscode': patch --- -Add public subpath entry points for path utilities and LSP request types +Define the public entry points with a package `exports` map -`@shopify/theme-check-common/path` and `@shopify/theme-language-server-common/types` are now public entry points. They re-export the same members as the package barrel, but importing them pulls in only that module instead of the whole package. +`@shopify/theme-check-common` now exports `.`, `./path`, `./test`, and `./package.json`. +`@shopify/theme-language-server-common` now exports `.`, `./types`, and `./package.json`. -The VS Code extension uses them to keep the language server out of the client bundle: `browser/extension.js` is 2.1 MB instead of 6.7 MB, and `node/extension.js` is 1.4 MB instead of 6.5 MB. The barrel imports still work exactly as before. +Importing a subpath pulls in only that module instead of the whole package. The VS Code extension +uses them to keep the language server out of the client bundle: `browser/extension.js` is 2.1 MB +instead of 6.7 MB, and `node/extension.js` is 1.4 MB instead of 6.5 MB. The barrel imports still +work exactly as before. + +**Breaking:** the `exports` map is now the complete public surface of both packages. Any `src/` or +`dist/` deep import that is not listed above is unsupported and no longer resolves — Node and +bundlers throw `ERR_PACKAGE_PATH_NOT_EXPORTED`. This encapsulation is the point of the major, not a +side effect. Note that under `moduleResolution: "node"` TypeScript does not model `exports`, so a +retired deep import can still type-check while failing at runtime; grep for +`theme-check-common/dist`, `theme-check-common/src`, `theme-language-server-common/dist` and +`theme-language-server-common/src` instead of relying on `tsc`. + +The test helpers keep a supported path: + +| Removed | Use instead | +| ------------------------------------------------------------------------------- | ---------------------------------- | +| `@shopify/theme-check-common/src/test`, `@shopify/theme-check-common/dist/test` | `@shopify/theme-check-common/test` | + +Seven symbols that were previously reachable only through a retired deep import are now exported +from the `@shopify/theme-check-common` barrel: + +| Symbol | Previously imported from | +| --------------------------------------- | ------------------------------------------------ | +| `getPosition` | `.../dist/utils` | +| `createDisabledChecksModule` | `.../dist/disabled-checks` | +| `UNMATCHED_COMMENT_CLOSE_PARSER_ERROR` | `.../dist/checks/liquid-syntax-error/comment` | +| `UNMATCHED_RAW_CLOSE_PARSER_ERROR` | `.../dist/checks/liquid-syntax-error/comment` | +| `hasRubyAcceptedInertCommentBodyCloser` | `.../dist/checks/liquid-syntax-error/comment` | +| `hasJavascriptClosingTagAfter` | `.../dist/checks/liquid-syntax-error/javascript` | +| `hasRubyAcceptedRawTagCloserWithMarkup` | `.../dist/checks/liquid-syntax-error/utils` | + +That is not a complete replacement table for the retired modules. Every other symbol they exposed is +intentionally private and has no barrel equivalent. In particular `getOffset` is **not** promoted: +two different implementations exist (`utils/position` and `checks/liquid-syntax-error/utils`) and +they disagree on out-of-range input, so no automatic replacement is offered. If you depend on a +symbol that is now private, open an issue so it can be promoted deliberately. diff --git a/packages/theme-check-common/package.json b/packages/theme-check-common/package.json index 5ce401cca..16cab8a99 100644 --- a/packages/theme-check-common/package.json +++ b/packages/theme-check-common/package.json @@ -4,6 +4,31 @@ "license": "MIT", "main": "dist/index.js", "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./path": { + "types": "./dist/path.d.ts", + "default": "./dist/path.js" + }, + "./test": { + "types": "./dist/test/index.d.ts", + "default": "./dist/test/index.js" + }, + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "path": [ + "dist/path.d.ts" + ], + "test": [ + "dist/test/index.d.ts" + ] + } + }, "author": "CP Clermont ", "homepage": "https://github.com/Shopify/theme-tools/tree/main/packages/theme-check-common#readme", "repository": { diff --git a/packages/theme-check-common/path.d.ts b/packages/theme-check-common/path.d.ts deleted file mode 100644 index cc2f65808..000000000 --- a/packages/theme-check-common/path.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/path'; diff --git a/packages/theme-check-common/path.js b/packages/theme-check-common/path.js deleted file mode 100644 index 886a4fcad..000000000 --- a/packages/theme-check-common/path.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/path'); diff --git a/packages/theme-check-common/src/index.ts b/packages/theme-check-common/src/index.ts index ba2464ce1..36d173bdb 100644 --- a/packages/theme-check-common/src/index.ts +++ b/packages/theme-check-common/src/index.ts @@ -41,7 +41,15 @@ import { visitJSON, visitLiquid } from './visitors'; export * from './AbstractFileSystem'; export * from './AugmentedThemeDocset'; export * from './checks'; +export { + UNMATCHED_COMMENT_CLOSE_PARSER_ERROR, + UNMATCHED_RAW_CLOSE_PARSER_ERROR, + hasRubyAcceptedInertCommentBodyCloser, +} from './checks/liquid-syntax-error/comment'; +export { hasJavascriptClosingTagAfter } from './checks/liquid-syntax-error/javascript'; +export { hasRubyAcceptedRawTagCloserWithMarkup } from './checks/liquid-syntax-error/utils'; export * from './context-utils'; +export { createDisabledChecksModule } from './disabled-checks'; export * from './find-root'; export * from './fixes'; export * from './ignore'; @@ -54,6 +62,7 @@ export * from './types'; export * from './utils/error'; export * from './utils/indexBy'; export * from './utils/memo'; +export { getPosition } from './utils/position'; export * from './utils/types'; export * from './utils/object'; export * from './utils/styles'; diff --git a/packages/theme-check-common/src/package-exports.spec.ts b/packages/theme-check-common/src/package-exports.spec.ts new file mode 100644 index 000000000..a5c84ab6f --- /dev/null +++ b/packages/theme-check-common/src/package-exports.spec.ts @@ -0,0 +1,55 @@ +import { createRequire } from 'node:module'; +import { describe, expect, it } from 'vitest'; + +const requireFromHere = createRequire(__filename); + +function resolutionErrorCode(specifier: string): string | undefined { + try { + requireFromHere.resolve(specifier); + return undefined; + } catch (error) { + return (error as NodeJS.ErrnoException).code; + } +} + +describe('Module: package exports', () => { + it.each([ + ['@shopify/theme-check-common', 'theme-check-common/dist/index.js'], + ['@shopify/theme-check-common/path', 'theme-check-common/dist/path.js'], + ['@shopify/theme-check-common/test', 'theme-check-common/dist/test/index.js'], + ['@shopify/theme-check-common/package.json', 'theme-check-common/package.json'], + ])('resolves %s', (specifier, suffix) => { + expect(requireFromHere.resolve(specifier).replace(/\\/g, '/')).toContain(suffix); + }); + + it.each([ + '@shopify/theme-check-common/src/index', + '@shopify/theme-check-common/src/test', + '@shopify/theme-check-common/dist/index', + '@shopify/theme-check-common/dist/test', + '@shopify/theme-check-common/dist/path', + '@shopify/theme-check-common/dist/utils', + '@shopify/theme-check-common/dist/disabled-checks', + '@shopify/theme-check-common/dist/checks/liquid-syntax-error/comment', + '@shopify/theme-check-common/dist/checks/liquid-syntax-error/javascript', + '@shopify/theme-check-common/dist/checks/liquid-syntax-error/utils', + ])('no longer exposes %s', (specifier) => { + expect(resolutionErrorCode(specifier)).toBe('ERR_PACKAGE_PATH_NOT_EXPORTED'); + }); + + it('exposes the promoted symbols on the barrel', () => { + const themeCheckCommon = requireFromHere('@shopify/theme-check-common'); + + for (const name of [ + 'getPosition', + 'createDisabledChecksModule', + 'UNMATCHED_COMMENT_CLOSE_PARSER_ERROR', + 'UNMATCHED_RAW_CLOSE_PARSER_ERROR', + 'hasRubyAcceptedInertCommentBodyCloser', + 'hasJavascriptClosingTagAfter', + 'hasRubyAcceptedRawTagCloserWithMarkup', + ]) { + expect(themeCheckCommon).toHaveProperty(name); + } + }); +}); diff --git a/packages/theme-language-server-common/package.json b/packages/theme-language-server-common/package.json index b2cd7e609..bdbf3e324 100644 --- a/packages/theme-language-server-common/package.json +++ b/packages/theme-language-server-common/package.json @@ -3,6 +3,24 @@ "version": "2.22.1", "main": "dist/index.js", "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./types": { + "types": "./dist/types.d.ts", + "default": "./dist/types.js" + }, + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "types": [ + "dist/types.d.ts" + ] + } + }, "author": "CP Clermont ", "homepage": "https://github.com/Shopify/theme-tools/tree/main/packages/theme-language-server-common#readme", "repository": { diff --git a/packages/theme-language-server-common/src/diagnostics/runChecks.spec.ts b/packages/theme-language-server-common/src/diagnostics/runChecks.spec.ts index 386ec6d22..1fc423f72 100644 --- a/packages/theme-language-server-common/src/diagnostics/runChecks.spec.ts +++ b/packages/theme-language-server-common/src/diagnostics/runChecks.spec.ts @@ -6,7 +6,7 @@ import { Severity, SourceCodeType, } from '@shopify/theme-check-common'; -import { MockFileSystem } from '@shopify/theme-check-common/src/test'; +import { MockFileSystem } from '@shopify/theme-check-common/test'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { Connection } from 'vscode-languageserver'; import { DocumentManager } from '../documents'; diff --git a/packages/theme-language-server-common/src/documents/DocumentManager.spec.ts b/packages/theme-language-server-common/src/documents/DocumentManager.spec.ts index 3ff9b5f65..7bf869af7 100644 --- a/packages/theme-language-server-common/src/documents/DocumentManager.spec.ts +++ b/packages/theme-language-server-common/src/documents/DocumentManager.spec.ts @@ -6,7 +6,7 @@ import { ThemeBlock, ThemeSchemaType, } from '@shopify/theme-check-common'; -import { MockFileSystem } from '@shopify/theme-check-common/src/test'; +import { MockFileSystem } from '@shopify/theme-check-common/test'; import { assert, beforeEach, describe, expect, it, vi } from 'vitest'; import { URI, Utils } from 'vscode-uri'; import { DocumentManager } from './DocumentManager'; diff --git a/packages/theme-language-server-common/src/hover/providers/LiquidDocTagHoverProvider.spec.ts b/packages/theme-language-server-common/src/hover/providers/LiquidDocTagHoverProvider.spec.ts index f0e94479f..e15922b7a 100644 --- a/packages/theme-language-server-common/src/hover/providers/LiquidDocTagHoverProvider.spec.ts +++ b/packages/theme-language-server-common/src/hover/providers/LiquidDocTagHoverProvider.spec.ts @@ -2,7 +2,6 @@ import { describe, beforeEach, it, expect } from 'vitest'; import { DocumentManager } from '../../documents'; import { HoverProvider } from '../HoverProvider'; import { MetafieldDefinitionMap } from '@shopify/theme-check-common'; -import '../../../../theme-check-common/src/test/test-setup'; import { formatLiquidDocTagHandle, SUPPORTED_LIQUID_DOC_TAG_HANDLES } from '../../utils/liquidDoc'; describe('Module: RenderSnippetParameterHoverProvider', async () => { diff --git a/packages/theme-language-server-common/src/package-exports.spec.ts b/packages/theme-language-server-common/src/package-exports.spec.ts new file mode 100644 index 000000000..a7b2a01bc --- /dev/null +++ b/packages/theme-language-server-common/src/package-exports.spec.ts @@ -0,0 +1,35 @@ +import { createRequire } from 'node:module'; +import { describe, expect, it } from 'vitest'; + +const requireFromHere = createRequire(__filename); + +function resolutionErrorCode(specifier: string): string | undefined { + try { + requireFromHere.resolve(specifier); + return undefined; + } catch (error) { + return (error as NodeJS.ErrnoException).code; + } +} + +describe('Module: package exports', () => { + it.each([ + ['@shopify/theme-language-server-common', 'theme-language-server-common/dist/index.js'], + ['@shopify/theme-language-server-common/types', 'theme-language-server-common/dist/types.js'], + [ + '@shopify/theme-language-server-common/package.json', + 'theme-language-server-common/package.json', + ], + ])('resolves %s', (specifier, suffix) => { + expect(requireFromHere.resolve(specifier).replace(/\\/g, '/')).toContain(suffix); + }); + + it.each([ + '@shopify/theme-language-server-common/src/index', + '@shopify/theme-language-server-common/src/types', + '@shopify/theme-language-server-common/dist/index', + '@shopify/theme-language-server-common/dist/types', + ])('no longer exposes %s', (specifier) => { + expect(resolutionErrorCode(specifier)).toBe('ERR_PACKAGE_PATH_NOT_EXPORTED'); + }); +}); diff --git a/packages/theme-language-server-common/src/renamed/handlers/AssetRenameHandler.spec.ts b/packages/theme-language-server-common/src/renamed/handlers/AssetRenameHandler.spec.ts index 5c1bd9b49..122279629 100644 --- a/packages/theme-language-server-common/src/renamed/handlers/AssetRenameHandler.spec.ts +++ b/packages/theme-language-server-common/src/renamed/handlers/AssetRenameHandler.spec.ts @@ -1,4 +1,4 @@ -import { MockFileSystem } from '@shopify/theme-check-common/src/test'; +import { MockFileSystem } from '@shopify/theme-check-common/test'; import { assert, beforeEach, describe, expect, it } from 'vitest'; import { TextDocumentEdit } from 'vscode-json-languageservice'; import { ApplyWorkspaceEditParams } from 'vscode-languageserver-protocol'; diff --git a/packages/theme-language-server-common/src/renamed/handlers/BlockRenameHandler.spec.ts b/packages/theme-language-server-common/src/renamed/handlers/BlockRenameHandler.spec.ts index 32f9bd6b2..5c9cfb018 100644 --- a/packages/theme-language-server-common/src/renamed/handlers/BlockRenameHandler.spec.ts +++ b/packages/theme-language-server-common/src/renamed/handlers/BlockRenameHandler.spec.ts @@ -1,4 +1,4 @@ -import { MockFileSystem } from '@shopify/theme-check-common/src/test'; +import { MockFileSystem } from '@shopify/theme-check-common/test'; import { assert, beforeEach, describe, expect, it } from 'vitest'; import { TextDocumentEdit } from 'vscode-json-languageservice'; import { ApplyWorkspaceEditParams } from 'vscode-languageserver-protocol'; diff --git a/packages/theme-language-server-common/src/renamed/handlers/SectionRenameHandler.spec.ts b/packages/theme-language-server-common/src/renamed/handlers/SectionRenameHandler.spec.ts index 2b8da2c2b..168ee5072 100644 --- a/packages/theme-language-server-common/src/renamed/handlers/SectionRenameHandler.spec.ts +++ b/packages/theme-language-server-common/src/renamed/handlers/SectionRenameHandler.spec.ts @@ -1,4 +1,4 @@ -import { MockFileSystem } from '@shopify/theme-check-common/src/test'; +import { MockFileSystem } from '@shopify/theme-check-common/test'; import { assert, beforeEach, describe, expect, it } from 'vitest'; import { TextDocumentEdit } from 'vscode-json-languageservice'; import { ApplyWorkspaceEditParams } from 'vscode-languageserver-protocol'; diff --git a/packages/theme-language-server-common/src/renamed/handlers/SnippetRenameHandler.spec.ts b/packages/theme-language-server-common/src/renamed/handlers/SnippetRenameHandler.spec.ts index b46a47c86..1eb37dea3 100644 --- a/packages/theme-language-server-common/src/renamed/handlers/SnippetRenameHandler.spec.ts +++ b/packages/theme-language-server-common/src/renamed/handlers/SnippetRenameHandler.spec.ts @@ -1,4 +1,4 @@ -import { MockFileSystem } from '@shopify/theme-check-common/src/test'; +import { MockFileSystem } from '@shopify/theme-check-common/test'; import { assert, beforeEach, describe, expect, it } from 'vitest'; import { TextDocumentEdit } from 'vscode-json-languageservice'; import { ApplyWorkspaceEditParams } from 'vscode-languageserver-protocol'; diff --git a/packages/theme-language-server-common/src/server/startServer.spec.ts b/packages/theme-language-server-common/src/server/startServer.spec.ts index 5f0bf8acb..22046b05c 100644 --- a/packages/theme-language-server-common/src/server/startServer.spec.ts +++ b/packages/theme-language-server-common/src/server/startServer.spec.ts @@ -1,5 +1,5 @@ import { allChecks, path } from '@shopify/theme-check-common'; -import { MockFileSystem, MockTheme } from '@shopify/theme-check-common/dist/test'; +import { MockFileSystem, MockTheme } from '@shopify/theme-check-common/test'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { DidChangeConfigurationNotification, diff --git a/packages/theme-language-server-common/src/tsconfig.json b/packages/theme-language-server-common/src/tsconfig.json index 5edd7c804..1ef4b731d 100644 --- a/packages/theme-language-server-common/src/tsconfig.json +++ b/packages/theme-language-server-common/src/tsconfig.json @@ -10,6 +10,7 @@ "lib": ["es2022", "dom"], "paths": { "@shopify/theme-check-common": ["../../theme-check-common/src"], + "@shopify/theme-check-common/test": ["../../theme-check-common/src/test"], "@shopify/liquid-html-parser": ["../../liquid-html-parser/src"], "@shopify/theme-graph": ["../../theme-graph/src"] } diff --git a/packages/theme-language-server-common/types.d.ts b/packages/theme-language-server-common/types.d.ts deleted file mode 100644 index 7236c51a0..000000000 --- a/packages/theme-language-server-common/types.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/types'; diff --git a/packages/theme-language-server-common/types.js b/packages/theme-language-server-common/types.js deleted file mode 100644 index d94f7183d..000000000 --- a/packages/theme-language-server-common/types.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/types'); diff --git a/tsconfig.json b/tsconfig.json index 340eaeca0..fe2943e8a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,8 +32,17 @@ "@shopify/theme-check-common": [ "./packages/theme-check-common/src/index" ], + "@shopify/theme-check-common/path": [ + "./packages/theme-check-common/src/path" + ], + "@shopify/theme-check-common/test": [ + "./packages/theme-check-common/src/test/index" + ], "@shopify/theme-language-server-common": [ "./packages/theme-language-server-common/src/index" + ], + "@shopify/theme-language-server-common/types": [ + "./packages/theme-language-server-common/src/types" ] }, // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ From eb0f259aab0e512718a62092f0d807fdc60f7285 Mon Sep 17 00:00:00 2001 From: Josh Faigan Date: Fri, 11 Sep 2026 14:30:04 -0400 Subject: [PATCH 4/4] docs(changeset): shorten exports migration notes --- .changeset/tiny-cycles-arrive.md | 50 +++++++++++--------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/.changeset/tiny-cycles-arrive.md b/.changeset/tiny-cycles-arrive.md index aedb33861..db3eb66bb 100644 --- a/.changeset/tiny-cycles-arrive.md +++ b/.changeset/tiny-cycles-arrive.md @@ -6,43 +6,27 @@ Define the public entry points with a package `exports` map -`@shopify/theme-check-common` now exports `.`, `./path`, `./test`, and `./package.json`. -`@shopify/theme-language-server-common` now exports `.`, `./types`, and `./package.json`. +- `@shopify/theme-check-common` exports `.`, `./path`, `./test`, and `./package.json`. +- `@shopify/theme-language-server-common` exports `.`, `./types`, and `./package.json`. Importing a subpath pulls in only that module instead of the whole package. The VS Code extension -uses them to keep the language server out of the client bundle: `browser/extension.js` is 2.1 MB -instead of 6.7 MB, and `node/extension.js` is 1.4 MB instead of 6.5 MB. The barrel imports still -work exactly as before. +uses this to keep the language server out of the client bundle: `browser/extension.js` is 2.1 MB +instead of 6.7 MB, and `node/extension.js` is 1.4 MB instead of 6.5 MB. Barrel imports still work +exactly as before. **Breaking:** the `exports` map is now the complete public surface of both packages. Any `src/` or -`dist/` deep import that is not listed above is unsupported and no longer resolves — Node and -bundlers throw `ERR_PACKAGE_PATH_NOT_EXPORTED`. This encapsulation is the point of the major, not a -side effect. Note that under `moduleResolution: "node"` TypeScript does not model `exports`, so a -retired deep import can still type-check while failing at runtime; grep for -`theme-check-common/dist`, `theme-check-common/src`, `theme-language-server-common/dist` and -`theme-language-server-common/src` instead of relying on `tsc`. +`dist/` deep import that is not listed above no longer resolves — Node and bundlers throw +`ERR_PACKAGE_PATH_NOT_EXPORTED`. -The test helpers keep a supported path: +To migrate: -| Removed | Use instead | -| ------------------------------------------------------------------------------- | ---------------------------------- | -| `@shopify/theme-check-common/src/test`, `@shopify/theme-check-common/dist/test` | `@shopify/theme-check-common/test` | +- Replace `@shopify/theme-check-common/src/test` or `.../dist/test` with + `@shopify/theme-check-common/test`. +- Seven symbols previously reachable only through a retired deep import are now exported from the + `@shopify/theme-check-common` barrel: `getPosition`, `createDisabledChecksModule`, + `UNMATCHED_COMMENT_CLOSE_PARSER_ERROR`, `UNMATCHED_RAW_CLOSE_PARSER_ERROR`, + `hasRubyAcceptedInertCommentBodyCloser`, `hasJavascriptClosingTagAfter`, and + `hasRubyAcceptedRawTagCloserWithMarkup`. -Seven symbols that were previously reachable only through a retired deep import are now exported -from the `@shopify/theme-check-common` barrel: - -| Symbol | Previously imported from | -| --------------------------------------- | ------------------------------------------------ | -| `getPosition` | `.../dist/utils` | -| `createDisabledChecksModule` | `.../dist/disabled-checks` | -| `UNMATCHED_COMMENT_CLOSE_PARSER_ERROR` | `.../dist/checks/liquid-syntax-error/comment` | -| `UNMATCHED_RAW_CLOSE_PARSER_ERROR` | `.../dist/checks/liquid-syntax-error/comment` | -| `hasRubyAcceptedInertCommentBodyCloser` | `.../dist/checks/liquid-syntax-error/comment` | -| `hasJavascriptClosingTagAfter` | `.../dist/checks/liquid-syntax-error/javascript` | -| `hasRubyAcceptedRawTagCloserWithMarkup` | `.../dist/checks/liquid-syntax-error/utils` | - -That is not a complete replacement table for the retired modules. Every other symbol they exposed is -intentionally private and has no barrel equivalent. In particular `getOffset` is **not** promoted: -two different implementations exist (`utils/position` and `checks/liquid-syntax-error/utils`) and -they disagree on out-of-range input, so no automatic replacement is offered. If you depend on a -symbol that is now private, open an issue so it can be promoted deliberately. +Every other symbol those modules exposed is intentionally private. If you depend on one, open an +issue so it can be promoted deliberately.