diff --git a/.changeset/tiny-cycles-arrive.md b/.changeset/tiny-cycles-arrive.md new file mode 100644 index 000000000..db3eb66bb --- /dev/null +++ b/.changeset/tiny-cycles-arrive.md @@ -0,0 +1,32 @@ +--- +'@shopify/theme-language-server-common': major +'@shopify/theme-check-common': major +'theme-check-vscode': patch +--- + +Define the public entry points with a package `exports` map + +- `@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 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 no longer resolves — Node and bundlers throw +`ERR_PACKAGE_PATH_NOT_EXPORTED`. + +To migrate: + +- 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`. + +Every other symbol those modules exposed is intentionally private. If you depend on one, 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/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/vscode-extension/src/browser/extension.ts b/packages/vscode-extension/src/browser/extension.ts index 074c1447b..ef4479b96 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/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 b08930701..76bbc9508 100644 --- a/packages/vscode-extension/src/common/ReferencesProvider.ts +++ b/packages/vscode-extension/src/common/ReferencesProvider.ts @@ -1,12 +1,11 @@ -import { path } from '@shopify/theme-check-common'; +import * as path from '@shopify/theme-check-common/path'; import { - AugmentedLocation, - AugmentedReference, ThemeGraphDependenciesRequest, ThemeGraphDidUpdateNotification, ThemeGraphReferenceRequest, ThemeGraphRootRequest, -} from '@shopify/theme-language-server-common'; +} 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 4a465e9d9..e55e73b1f 100644 --- a/packages/vscode-extension/src/common/VsCodeFileSystem.ts +++ b/packages/vscode-extension/src/common/VsCodeFileSystem.ts @@ -1,4 +1,4 @@ -import { AbstractFileSystem, FileTuple, FileStat } from '@shopify/theme-check-common'; +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 12c5f59e7..a2469544e 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/path'; import { - AugmentedLocation, ThemeGraphDeadCodeRequest, ThemeGraphRootRequest, -} from '@shopify/theme-language-server-common'; +} 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 0bf9b99fc..bef002b6e 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/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 { 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'. */