@wyw-in-js/turbopack-loader 2.1.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.js CHANGED
@@ -16,6 +16,28 @@ const stripQueryAndHash = (request) => {
16
16
  if (hashIdx === -1) return request.slice(0, queryIdx);
17
17
  return request.slice(0, Math.min(queryIdx, hashIdx));
18
18
  };
19
+ const getPackageNameForSubpath = (request) => {
20
+ const fileRequest = stripQueryAndHash(request);
21
+ if (fileRequest.startsWith(".") || path.isAbsolute(fileRequest) || path.win32.isAbsolute(fileRequest)) {
22
+ return null;
23
+ }
24
+ const parts = fileRequest.split("/");
25
+ if (fileRequest.startsWith("@")) {
26
+ const [scope, name] = parts;
27
+ if (parts.length <= 2 || scope.length <= 1 || !name) {
28
+ return null;
29
+ }
30
+ return `${scope}/${name}`;
31
+ }
32
+ if (fileRequest.startsWith("#") || parts.length <= 1 || !parts[0]) {
33
+ return null;
34
+ }
35
+ return parts[0];
36
+ };
37
+ const isTurbopackPackageSubpathResolveError = (request, error) => {
38
+ const packageName = getPackageNameForSubpath(request);
39
+ return packageName !== null && error instanceof Error && error.message.includes(`Unable to resolve module '${packageName}' with subpath`);
40
+ };
19
41
  const cache = new TransformCacheCollection();
20
42
  function convertSourceMap(value, filename) {
21
43
  if (typeof value === "string" || !value) {
@@ -70,6 +92,15 @@ const turbopackLoader = function turbopackLoader(content, inputSourceMap) {
70
92
  }
71
93
  return result;
72
94
  };
95
+ const addResolvedDependency = async (dependency) => {
96
+ try {
97
+ await asyncResolve(dependency, this.resourcePath);
98
+ } catch (error) {
99
+ if (!isTurbopackPackageSubpathResolveError(dependency, error)) {
100
+ throw error;
101
+ }
102
+ }
103
+ };
73
104
  const transformServices = {
74
105
  options: {
75
106
  filename: this.resourcePath,
@@ -98,7 +129,7 @@ const turbopackLoader = function turbopackLoader(content, inputSourceMap) {
98
129
  if (sourceMap && typeof result.cssSourceMapText !== "undefined") {
99
130
  cssText += `\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(result.cssSourceMapText).toString("base64")}*/\n`;
100
131
  }
101
- await Promise.all((result.dependencies ?? []).map((dep) => asyncResolve(dep, this.resourcePath)));
132
+ await Promise.all((result.dependencies ?? []).map((dep) => addResolvedDependency(dep)));
102
133
  if (outputCss) {
103
134
  callback(null, cssText);
104
135
  return;
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","names":[],"sources":["../src/index.ts"],"version":3,"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { RawSourceMap } from 'source-map';\nimport type { LoaderContext, RawLoaderDefinitionFunction } from 'webpack';\n\nimport { logger } from '@wyw-in-js/shared';\nimport type { PluginOptions, Result } from '@wyw-in-js/transform';\nimport { transform, TransformCacheCollection } from '@wyw-in-js/transform';\n\nimport { makeCssModuleGlobal } from './css-modules';\nimport { writeFileIfChanged } from './file-utils';\nimport { insertImportStatement } from './insert-import';\n\nconst DEFAULT_EXTENSION = '.wyw-in-js.module.css';\nconst CSS_OUTPUT_QUERY = '__wyw_css';\n\nconst stripQueryAndHash = (request: string) => {\n const queryIdx = request.indexOf('?');\n const hashIdx = request.indexOf('#');\n\n if (queryIdx === -1) {\n return hashIdx === -1 ? request : request.slice(0, hashIdx);\n }\n if (hashIdx === -1) return request.slice(0, queryIdx);\n\n return request.slice(0, Math.min(queryIdx, hashIdx));\n};\n\nexport type LoaderOptions = {\n cssOutputMode?: 'sidecar' | 'query';\n keepComments?: boolean;\n outputCss?: boolean;\n prefixer?: boolean;\n sourceMap?: boolean;\n} & Partial<PluginOptions>;\n\ntype Loader = RawLoaderDefinitionFunction<LoaderOptions>;\ntype ResolveFn = ReturnType<LoaderContext<LoaderOptions>['getResolve']>;\n\nconst cache = new TransformCacheCollection();\n\nfunction convertSourceMap(\n value: RawSourceMap | string | null | undefined,\n filename: string\n): RawSourceMap | undefined {\n if (typeof value === 'string' || !value) {\n return undefined;\n }\n\n return {\n ...value,\n file: value.file ?? filename,\n mappings: value.mappings ?? '',\n names: value.names ?? [],\n sources: value.sources ?? [],\n version: value.version ?? 3,\n };\n}\n\nasync function resolveWith(\n resolve: ResolveFn,\n context: string,\n request: string\n): Promise<string | false> {\n type ResolveCallback = (\n ctx: string,\n req: string,\n cb: (err: Error | null, result?: string) => void\n ) => void;\n type ResolveAsync = (ctx: string, req: string) => Promise<string | false>;\n\n if (typeof resolve !== 'function') return false;\n\n if (resolve.length >= 3) {\n return new Promise((ok, fail) => {\n (resolve as unknown as ResolveCallback)(\n context,\n request,\n (err, result) => {\n if (err) fail(err);\n else ok(result ?? false);\n }\n );\n });\n }\n\n return (resolve as unknown as ResolveAsync)(context, request);\n}\n\nconst turbopackLoader: Loader = function turbopackLoader(\n content,\n inputSourceMap\n) {\n const callbackFromAsync =\n typeof this.async === 'function' ? this.async() : undefined;\n const callback =\n typeof callbackFromAsync === 'function' ? callbackFromAsync : this.callback;\n\n if (typeof callback !== 'function') {\n throw new Error('Async loader callback is not available');\n }\n\n logger('turbopack-loader %s', this.resourcePath);\n\n const {\n sourceMap,\n keepComments,\n outputCss,\n cssOutputMode = 'sidecar',\n prefixer,\n configFile,\n ...rest\n } = this.getOptions() || {};\n\n if (configFile) {\n const configPath = path.isAbsolute(configFile)\n ? configFile\n : path.join(process.cwd(), configFile);\n this.addDependency(configPath);\n }\n\n const cssFileName = `${path.basename(\n this.resourcePath,\n path.extname(this.resourcePath)\n )}${DEFAULT_EXTENSION}`;\n const cssFilePath = path.join(path.dirname(this.resourcePath), cssFileName);\n const cssImportPath = `./${cssFileName}`;\n\n const resolveModule = this.getResolve({ dependencyType: 'esm' });\n\n const asyncResolve = async (token: string, importer: string) => {\n const context = path.isAbsolute(importer)\n ? path.dirname(importer)\n : path.join(process.cwd(), path.dirname(importer));\n\n const result = await resolveWith(resolveModule, context, token);\n\n if (!result) {\n throw new Error(`Cannot resolve ${token} from ${context}`);\n }\n\n const filePath = stripQueryAndHash(result);\n if (path.isAbsolute(filePath)) {\n this.addDependency(filePath);\n }\n\n return result;\n };\n\n const transformServices = {\n options: {\n filename: this.resourcePath,\n inputSourceMap: convertSourceMap(inputSourceMap, this.resourcePath),\n pluginOptions: { configFile, ...rest },\n prefixer,\n keepComments,\n root: process.cwd(),\n },\n cache,\n emitWarning: (message: string) => {\n if (typeof this.emitWarning === 'function') {\n const warning = new Error(message);\n delete warning.stack;\n this.emitWarning(warning);\n }\n },\n };\n\n transform(transformServices, content.toString(), asyncResolve)\n .then(async (result: Result) => {\n const rawCssText = result.cssText ?? '';\n\n if (rawCssText.trim()) {\n let cssText = makeCssModuleGlobal(rawCssText);\n\n if (sourceMap && typeof result.cssSourceMapText !== 'undefined') {\n cssText += `\\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(\n result.cssSourceMapText\n ).toString('base64')}*/\\n`;\n }\n\n await Promise.all(\n (result.dependencies ?? []).map((dep) =>\n asyncResolve(dep, this.resourcePath)\n )\n );\n\n if (outputCss) {\n callback(null, cssText);\n return;\n }\n\n let importPath = cssImportPath;\n if (cssOutputMode === 'query') {\n importPath = `./${path.basename(\n this.resourcePath\n )}?${CSS_OUTPUT_QUERY}`;\n } else {\n writeFileIfChanged(cssFilePath, cssText);\n }\n\n const importStatement = `import ${JSON.stringify(importPath)};`;\n const finalCode = insertImportStatement(result.code, importStatement);\n\n callback(null, finalCode, result.sourceMap ?? undefined);\n return;\n }\n\n if (outputCss) {\n callback(null, '');\n return;\n }\n\n if (cssOutputMode !== 'query' && fs.existsSync(cssFilePath)) {\n writeFileIfChanged(cssFilePath, '');\n }\n\n callback(null, result.code, result.sourceMap ?? undefined);\n })\n .catch((err: Error) => callback(err));\n};\n\nexport default turbopackLoader;\n"],"file":"index.js"}
1
+ {"mappings":"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","names":[],"sources":["../src/index.ts"],"version":3,"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { RawSourceMap } from 'source-map';\nimport type { LoaderContext, RawLoaderDefinitionFunction } from 'webpack';\n\nimport { logger } from '@wyw-in-js/shared';\nimport type { PluginOptions, Result } from '@wyw-in-js/transform';\nimport { transform, TransformCacheCollection } from '@wyw-in-js/transform';\n\nimport { makeCssModuleGlobal } from './css-modules';\nimport { writeFileIfChanged } from './file-utils';\nimport { insertImportStatement } from './insert-import';\n\nconst DEFAULT_EXTENSION = '.wyw-in-js.module.css';\nconst CSS_OUTPUT_QUERY = '__wyw_css';\n\nconst stripQueryAndHash = (request: string) => {\n const queryIdx = request.indexOf('?');\n const hashIdx = request.indexOf('#');\n\n if (queryIdx === -1) {\n return hashIdx === -1 ? request : request.slice(0, hashIdx);\n }\n if (hashIdx === -1) return request.slice(0, queryIdx);\n\n return request.slice(0, Math.min(queryIdx, hashIdx));\n};\n\nconst getPackageNameForSubpath = (request: string) => {\n const fileRequest = stripQueryAndHash(request);\n if (\n fileRequest.startsWith('.') ||\n path.isAbsolute(fileRequest) ||\n path.win32.isAbsolute(fileRequest)\n ) {\n return null;\n }\n\n const parts = fileRequest.split('/');\n\n if (fileRequest.startsWith('@')) {\n const [scope, name] = parts;\n if (parts.length <= 2 || scope.length <= 1 || !name) {\n return null;\n }\n\n return `${scope}/${name}`;\n }\n\n if (fileRequest.startsWith('#') || parts.length <= 1 || !parts[0]) {\n return null;\n }\n\n return parts[0];\n};\n\nconst isTurbopackPackageSubpathResolveError = (\n request: string,\n error: unknown\n) => {\n const packageName = getPackageNameForSubpath(request);\n\n return (\n packageName !== null &&\n error instanceof Error &&\n error.message.includes(\n `Unable to resolve module '${packageName}' with subpath`\n )\n );\n};\n\nexport type LoaderOptions = {\n cssOutputMode?: 'sidecar' | 'query';\n keepComments?: boolean;\n outputCss?: boolean;\n prefixer?: boolean;\n sourceMap?: boolean;\n} & Partial<PluginOptions>;\n\ntype Loader = RawLoaderDefinitionFunction<LoaderOptions>;\ntype ResolveFn = ReturnType<LoaderContext<LoaderOptions>['getResolve']>;\n\nconst cache = new TransformCacheCollection();\n\nfunction convertSourceMap(\n value: RawSourceMap | string | null | undefined,\n filename: string\n): RawSourceMap | undefined {\n if (typeof value === 'string' || !value) {\n return undefined;\n }\n\n return {\n ...value,\n file: value.file ?? filename,\n mappings: value.mappings ?? '',\n names: value.names ?? [],\n sources: value.sources ?? [],\n version: value.version ?? 3,\n };\n}\n\nasync function resolveWith(\n resolve: ResolveFn,\n context: string,\n request: string\n): Promise<string | false> {\n type ResolveCallback = (\n ctx: string,\n req: string,\n cb: (err: Error | null, result?: string) => void\n ) => void;\n type ResolveAsync = (ctx: string, req: string) => Promise<string | false>;\n\n if (typeof resolve !== 'function') return false;\n\n if (resolve.length >= 3) {\n return new Promise((ok, fail) => {\n (resolve as unknown as ResolveCallback)(\n context,\n request,\n (err, result) => {\n if (err) fail(err);\n else ok(result ?? false);\n }\n );\n });\n }\n\n return (resolve as unknown as ResolveAsync)(context, request);\n}\n\nconst turbopackLoader: Loader = function turbopackLoader(\n content,\n inputSourceMap\n) {\n const callbackFromAsync =\n typeof this.async === 'function' ? this.async() : undefined;\n const callback =\n typeof callbackFromAsync === 'function' ? callbackFromAsync : this.callback;\n\n if (typeof callback !== 'function') {\n throw new Error('Async loader callback is not available');\n }\n\n logger('turbopack-loader %s', this.resourcePath);\n\n const {\n sourceMap,\n keepComments,\n outputCss,\n cssOutputMode = 'sidecar',\n prefixer,\n configFile,\n ...rest\n } = this.getOptions() || {};\n\n if (configFile) {\n const configPath = path.isAbsolute(configFile)\n ? configFile\n : path.join(process.cwd(), configFile);\n this.addDependency(configPath);\n }\n\n const cssFileName = `${path.basename(\n this.resourcePath,\n path.extname(this.resourcePath)\n )}${DEFAULT_EXTENSION}`;\n const cssFilePath = path.join(path.dirname(this.resourcePath), cssFileName);\n const cssImportPath = `./${cssFileName}`;\n\n const resolveModule = this.getResolve({ dependencyType: 'esm' });\n\n const asyncResolve = async (token: string, importer: string) => {\n const context = path.isAbsolute(importer)\n ? path.dirname(importer)\n : path.join(process.cwd(), path.dirname(importer));\n\n const result = await resolveWith(resolveModule, context, token);\n\n if (!result) {\n throw new Error(`Cannot resolve ${token} from ${context}`);\n }\n\n const filePath = stripQueryAndHash(result);\n if (path.isAbsolute(filePath)) {\n this.addDependency(filePath);\n }\n\n return result;\n };\n\n const addResolvedDependency = async (dependency: string) => {\n try {\n await asyncResolve(dependency, this.resourcePath);\n } catch (error) {\n if (!isTurbopackPackageSubpathResolveError(dependency, error)) {\n throw error;\n }\n }\n };\n\n const transformServices = {\n options: {\n filename: this.resourcePath,\n inputSourceMap: convertSourceMap(inputSourceMap, this.resourcePath),\n pluginOptions: { configFile, ...rest },\n prefixer,\n keepComments,\n root: process.cwd(),\n },\n cache,\n emitWarning: (message: string) => {\n if (typeof this.emitWarning === 'function') {\n const warning = new Error(message);\n delete warning.stack;\n this.emitWarning(warning);\n }\n },\n };\n\n transform(transformServices, content.toString(), asyncResolve)\n .then(async (result: Result) => {\n const rawCssText = result.cssText ?? '';\n\n if (rawCssText.trim()) {\n let cssText = makeCssModuleGlobal(rawCssText);\n\n if (sourceMap && typeof result.cssSourceMapText !== 'undefined') {\n cssText += `\\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(\n result.cssSourceMapText\n ).toString('base64')}*/\\n`;\n }\n\n await Promise.all(\n (result.dependencies ?? []).map((dep) => addResolvedDependency(dep))\n );\n\n if (outputCss) {\n callback(null, cssText);\n return;\n }\n\n let importPath = cssImportPath;\n if (cssOutputMode === 'query') {\n importPath = `./${path.basename(\n this.resourcePath\n )}?${CSS_OUTPUT_QUERY}`;\n } else {\n writeFileIfChanged(cssFilePath, cssText);\n }\n\n const importStatement = `import ${JSON.stringify(importPath)};`;\n const finalCode = insertImportStatement(result.code, importStatement);\n\n callback(null, finalCode, result.sourceMap ?? undefined);\n return;\n }\n\n if (outputCss) {\n callback(null, '');\n return;\n }\n\n if (cssOutputMode !== 'query' && fs.existsSync(cssFilePath)) {\n writeFileIfChanged(cssFilePath, '');\n }\n\n callback(null, result.code, result.sourceMap ?? undefined);\n })\n .catch((err: Error) => callback(err));\n};\n\nexport default turbopackLoader;\n"],"file":"index.js"}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@wyw-in-js/turbopack-loader",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "@wyw-in-js/shared": "2.1.0",
7
- "@wyw-in-js/transform": "2.1.2"
7
+ "@wyw-in-js/transform": "2.1.3"
8
8
  },
9
9
  "devDependencies": {
10
10
  "@types/node": "^22.0.0",
package/types/index.js CHANGED
@@ -17,6 +17,32 @@ const stripQueryAndHash = (request) => {
17
17
  return request.slice(0, queryIdx);
18
18
  return request.slice(0, Math.min(queryIdx, hashIdx));
19
19
  };
20
+ const getPackageNameForSubpath = (request) => {
21
+ const fileRequest = stripQueryAndHash(request);
22
+ if (fileRequest.startsWith('.') ||
23
+ path.isAbsolute(fileRequest) ||
24
+ path.win32.isAbsolute(fileRequest)) {
25
+ return null;
26
+ }
27
+ const parts = fileRequest.split('/');
28
+ if (fileRequest.startsWith('@')) {
29
+ const [scope, name] = parts;
30
+ if (parts.length <= 2 || scope.length <= 1 || !name) {
31
+ return null;
32
+ }
33
+ return `${scope}/${name}`;
34
+ }
35
+ if (fileRequest.startsWith('#') || parts.length <= 1 || !parts[0]) {
36
+ return null;
37
+ }
38
+ return parts[0];
39
+ };
40
+ const isTurbopackPackageSubpathResolveError = (request, error) => {
41
+ const packageName = getPackageNameForSubpath(request);
42
+ return (packageName !== null &&
43
+ error instanceof Error &&
44
+ error.message.includes(`Unable to resolve module '${packageName}' with subpath`));
45
+ };
20
46
  const cache = new TransformCacheCollection();
21
47
  function convertSourceMap(value, filename) {
22
48
  if (typeof value === 'string' || !value) {
@@ -78,6 +104,16 @@ const turbopackLoader = function turbopackLoader(content, inputSourceMap) {
78
104
  }
79
105
  return result;
80
106
  };
107
+ const addResolvedDependency = async (dependency) => {
108
+ try {
109
+ await asyncResolve(dependency, this.resourcePath);
110
+ }
111
+ catch (error) {
112
+ if (!isTurbopackPackageSubpathResolveError(dependency, error)) {
113
+ throw error;
114
+ }
115
+ }
116
+ };
81
117
  const transformServices = {
82
118
  options: {
83
119
  filename: this.resourcePath,
@@ -104,7 +140,7 @@ const turbopackLoader = function turbopackLoader(content, inputSourceMap) {
104
140
  if (sourceMap && typeof result.cssSourceMapText !== 'undefined') {
105
141
  cssText += `\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(result.cssSourceMapText).toString('base64')}*/\n`;
106
142
  }
107
- await Promise.all((result.dependencies ?? []).map((dep) => asyncResolve(dep, this.resourcePath)));
143
+ await Promise.all((result.dependencies ?? []).map((dep) => addResolvedDependency(dep)));
108
144
  if (outputCss) {
109
145
  callback(null, cssText);
110
146
  return;