From ee8b900ec65644d7b4b851e0060e0e3a7d3182e5 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 26 Jun 2026 14:52:03 +0400 Subject: [PATCH 1/3] Fix sideffect npm install size --- packages/sideffect/package.json | 10 +-- .../sideffect/src/vite/workflow-discovery.ts | 62 ++++++++++++++++--- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/packages/sideffect/package.json b/packages/sideffect/package.json index 8594cfc..cfaf78a 100644 --- a/packages/sideffect/package.json +++ b/packages/sideffect/package.json @@ -33,9 +33,6 @@ "prepublishOnly": "vp run build", "prepare": "vp config" }, - "dependencies": { - "typescript": ">=5.0.0 <7" - }, "devDependencies": { "@cloudflare/vite-plugin": "^1.40.0", "@cloudflare/workers-types": "4.20260605.1", @@ -44,12 +41,14 @@ "bumpp": "11.1.0", "defu": "6.1.7", "effect": "4.0.0-beta.78", + "typescript": "catalog:", "vite-plus": "catalog:" }, "peerDependencies": { "@cloudflare/vite-plugin": "^1.40.0", "@cloudflare/workers-types": ">=4.20260605.1", - "effect": ">=4.0.0-beta.75" + "effect": ">=4.0.0-beta.75", + "typescript": ">=5.0.0 <7" }, "peerDependenciesMeta": { "@cloudflare/vite-plugin": { @@ -57,6 +56,9 @@ }, "@cloudflare/workers-types": { "optional": true + }, + "typescript": { + "optional": true } }, "inlinedDependencies": { diff --git a/packages/sideffect/src/vite/workflow-discovery.ts b/packages/sideffect/src/vite/workflow-discovery.ts index f5a5513..b9a1100 100644 --- a/packages/sideffect/src/vite/workflow-discovery.ts +++ b/packages/sideffect/src/vite/workflow-discovery.ts @@ -1,7 +1,9 @@ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { createRequire } from "node:module"; import { dirname, extname, join, resolve } from "node:path"; -import ts from "typescript"; +import { Cause, Effect, Exit } from "effect"; +import type * as TypeScript from "typescript"; import { validateWorkflowExportName } from "../entrypoints.ts"; import type { WorkflowConfigEntry } from "../types.ts"; @@ -18,6 +20,46 @@ const sourceFileExtensions = new Set([ ]); const declarationFileExtensions = [".d.ts", ".d.mts", ".d.cts"]; const identifierName = /^[$A-Z_a-z][$\w]*$/; +type TypeScriptModule = typeof TypeScript; + +class TypeScriptWorkflowDiscoveryError extends Error { + constructor(cause: unknown) { + super( + 'Sideffect workflow discovery requires TypeScript\'s parser, but the optional peer dependency "typescript" could not be resolved. Install TypeScript in the project that uses `sideffect/vite`, for example `npm install -D typescript`. Runtime usage of `sideffect` and `sideffect/cloudflare` is unaffected.', + { cause }, + ); + this.name = "TypeScriptWorkflowDiscoveryError"; + } +} + +const require = createRequire(import.meta.url); +let loadedTypeScript: TypeScriptModule | undefined; + +function loadTypeScript(): TypeScriptModule { + if (loadedTypeScript) { + return loadedTypeScript; + } + + const loaded = Effect.runSyncExit( + Effect.try({ + try: () => require("typescript") as TypeScriptModule, + catch: (cause) => new TypeScriptWorkflowDiscoveryError(cause), + }), + ); + + if (Exit.isSuccess(loaded)) { + loadedTypeScript = loaded.value; + return loaded.value; + } + + throw Cause.squash(loaded.cause); +} + +const ts = new Proxy({} as TypeScriptModule, { + get(_target, property) { + return loadTypeScript()[property as keyof TypeScriptModule]; + }, +}); /** Workflow source paths scanned for static `Workflow.make(...).toLayer(...)` exports. */ export type WorkflowDiscoveryPaths = Array; @@ -407,7 +449,7 @@ function analyzeWorkflowSourceFile( return { exports, definitionExports, reExports }; } -function collectWorkflowBindings(sourceFile: ts.SourceFile): { +function collectWorkflowBindings(sourceFile: TypeScript.SourceFile): { readonly names: Set; readonly namespaces: Set; } { @@ -446,7 +488,7 @@ function collectWorkflowBindings(sourceFile: ts.SourceFile): { } function collectImportedWorkflowDefinitions( - sourceFile: ts.SourceFile, + sourceFile: TypeScript.SourceFile, filePath: string, visited: Set, ): Map { @@ -470,7 +512,7 @@ function collectImportedWorkflowDefinitions( return definitions; } -function collectLocalImports(sourceFile: ts.SourceFile): Array { +function collectLocalImports(sourceFile: TypeScript.SourceFile): Array { return sourceFile.statements.flatMap((statement) => { if ( !ts.isImportDeclaration(statement) || @@ -515,7 +557,7 @@ function collectLocalImports(sourceFile: ts.SourceFile): Array; readonly namespaces: Set }, workflowDefinitions: Map, ): string | undefined { @@ -538,7 +580,7 @@ function workflowNameFromLayerExpression( } function workflowNameFromMakeCall( - expression: ts.Expression, + expression: TypeScript.Expression, workflowBindings: { readonly names: Set; readonly namespaces: Set }, ): string | undefined { const call = skipOuterExpressions(expression); @@ -595,8 +637,8 @@ function workflowNameFromMakeCall( } function exportSpecifierNames( - declaration: ts.ExportDeclaration, - exports: ts.NamedExports, + declaration: TypeScript.ExportDeclaration, + exports: TypeScript.NamedExports, ): Array<{ readonly imported: string; readonly exported: string }> { if (declaration.isTypeOnly) { return []; @@ -626,7 +668,7 @@ function isLocalSpecifier(specifier: string): boolean { return specifier.startsWith(".") || specifier.startsWith("/"); } -function skipOuterExpressions(expression: ts.Expression): ts.Expression { +function skipOuterExpressions(expression: TypeScript.Expression): TypeScript.Expression { let current = expression; while ( ts.isParenthesizedExpression(current) || @@ -640,7 +682,7 @@ function skipOuterExpressions(expression: ts.Expression): ts.Expression { return current; } -function scriptKindForFile(path: string): ts.ScriptKind { +function scriptKindForFile(path: string): TypeScript.ScriptKind { switch (extname(path)) { case ".tsx": return ts.ScriptKind.TSX; From ef7b2514dc02a41f45a46405dd2d990d1d980cf5 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 26 Jun 2026 20:22:05 +0400 Subject: [PATCH 2/3] Remove TypeScript peer constraint --- bun.lock | 4 +--- packages/sideffect/package.json | 6 +----- packages/sideffect/src/vite/workflow-discovery.ts | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/bun.lock b/bun.lock index e79b1d0..5977588 100644 --- a/bun.lock +++ b/bun.lock @@ -12,9 +12,6 @@ "packages/sideffect": { "name": "sideffect", "version": "0.2.1", - "dependencies": { - "typescript": ">=5.0.0 <7", - }, "devDependencies": { "@cloudflare/vite-plugin": "^1.40.0", "@cloudflare/workers-types": "4.20260605.1", @@ -23,6 +20,7 @@ "bumpp": "11.1.0", "defu": "6.1.7", "effect": "4.0.0-beta.78", + "typescript": "catalog:", "vite-plus": "catalog:", }, "peerDependencies": { diff --git a/packages/sideffect/package.json b/packages/sideffect/package.json index cfaf78a..e867444 100644 --- a/packages/sideffect/package.json +++ b/packages/sideffect/package.json @@ -47,8 +47,7 @@ "peerDependencies": { "@cloudflare/vite-plugin": "^1.40.0", "@cloudflare/workers-types": ">=4.20260605.1", - "effect": ">=4.0.0-beta.75", - "typescript": ">=5.0.0 <7" + "effect": ">=4.0.0-beta.75" }, "peerDependenciesMeta": { "@cloudflare/vite-plugin": { @@ -56,9 +55,6 @@ }, "@cloudflare/workers-types": { "optional": true - }, - "typescript": { - "optional": true } }, "inlinedDependencies": { diff --git a/packages/sideffect/src/vite/workflow-discovery.ts b/packages/sideffect/src/vite/workflow-discovery.ts index b9a1100..f9d5657 100644 --- a/packages/sideffect/src/vite/workflow-discovery.ts +++ b/packages/sideffect/src/vite/workflow-discovery.ts @@ -25,7 +25,7 @@ type TypeScriptModule = typeof TypeScript; class TypeScriptWorkflowDiscoveryError extends Error { constructor(cause: unknown) { super( - 'Sideffect workflow discovery requires TypeScript\'s parser, but the optional peer dependency "typescript" could not be resolved. Install TypeScript in the project that uses `sideffect/vite`, for example `npm install -D typescript`. Runtime usage of `sideffect` and `sideffect/cloudflare` is unaffected.', + 'Sideffect workflow discovery requires TypeScript\'s parser, but the "typescript" package could not be resolved. Install TypeScript in the project that uses `sideffect/vite`, for example `npm install -D typescript`. Runtime usage of `sideffect` and `sideffect/cloudflare` is unaffected.', { cause }, ); this.name = "TypeScriptWorkflowDiscoveryError"; From c94f38caecfb64a25e701a09e0588b665f801a82 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 26 Jun 2026 20:36:47 +0400 Subject: [PATCH 3/3] Add changeset --- .changeset/new-coins-chew.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/new-coins-chew.md diff --git a/.changeset/new-coins-chew.md b/.changeset/new-coins-chew.md new file mode 100644 index 0000000..71c6438 --- /dev/null +++ b/.changeset/new-coins-chew.md @@ -0,0 +1,7 @@ +--- +"sideffect": patch +--- + +- Remove TypeScript from the Sideffect runtime dependency graph to reduce install size. +- Lazy-load the consuming project's TypeScript parser only when the Vite workflow discovery adapter scans workflow files. +- Avoid a TypeScript peer range so beta and RC releases are not blocked by npm prerelease range matching.