@ms-cloudpack/bundle-server 0.8.56 → 0.9.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"handleBundleRequest.d.ts","sourceRoot":"","sources":["../src/handleBundleRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACpH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAK1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAU1E,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,mBAAmB,GAAG;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;CACf,EACD,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CA2Lf"}
1
+ {"version":3,"file":"handleBundleRequest.d.ts","sourceRoot":"","sources":["../src/handleBundleRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACpH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAK1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAW1E,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,mBAAmB,GAAG;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;CACf,EACD,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CA2Nf"}
@@ -4,6 +4,7 @@ import { findResolveMapEntry } from '@ms-cloudpack/package-utilities';
4
4
  import { normalizeRelativePath, slash } from '@ms-cloudpack/path-string-parsing';
5
5
  import path from 'path';
6
6
  import { handleWorker } from './handleWorker.js';
7
+ import { rewriteImportsFromFile } from './rewriteImports.js';
7
8
  import { getLinkedPackageRedirectUrl } from './getLinkedPackageRedirectUrl.js';
8
9
  import { logResponse, sendErrorResponse } from './responseHelpers.js';
9
10
  const maxAge = 31536000; // 1 year
@@ -126,12 +127,39 @@ export async function handleBundleRequest(options, context) {
126
127
  !worker &&
127
128
  // Currently, only webpack and rspack setup isWorker in the result.
128
129
  result.outputFiles?.find((file) => file.isWorker && file.outputPath === normalizeRelativePath(filePath))) {
129
- await handleWorker({ req, res }, context);
130
+ await handleWorker({
131
+ req,
132
+ res,
133
+ workerFilePath: path.join(result.outputPath, filePath),
134
+ }, context);
130
135
  return;
131
136
  }
137
+ const fileFullPath = path.join(result.outputPath, filePath);
138
+ // If rewriteImports query param is set, rewrite bare imports in the file
139
+ // This is used for files imported by workers to ensure nested imports also work
140
+ if (req.query.rewriteimports !== undefined && session.importMap) {
141
+ try {
142
+ const rewrittenSource = await rewriteImportsFromFile(fileFullPath, context);
143
+ logResponse({ status: 200, requestPath: packageRequestPath, message: 'Returning file with rewritten imports' });
144
+ // Do not cache these responses as they are based on the import map at request time.
145
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
146
+ res.type('text/javascript').send(rewrittenSource);
147
+ return;
148
+ }
149
+ catch (err) {
150
+ const error = err;
151
+ console.error('Failed to rewrite imports for', packageRequestPath, ':', error);
152
+ return sendErrorResponse({
153
+ res,
154
+ status: 500,
155
+ requestPath: packageRequestPath,
156
+ message: `Failed to rewrite imports: ${error.message}`,
157
+ });
158
+ }
159
+ }
132
160
  sendFile({
133
161
  res,
134
- fileFullPath: path.join(result.outputPath, filePath),
162
+ fileFullPath,
135
163
  requestPath: packageRequestPath,
136
164
  parentPath: result.outputPath,
137
165
  isBundled: true,
@@ -1 +1 @@
1
- {"version":3,"file":"handleBundleRequest.js","sourceRoot":"","sources":["../src/handleBundleRequest.ts"],"names":[],"mappings":"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","sourcesContent":["import { ensurePackageBundled, addPackageOverride, errorEntrySource, type Context } from '@ms-cloudpack/api-server';\nimport type { Request, Response } from '@ms-cloudpack/create-express-app';\nimport { parseRequestInfo } from '@ms-cloudpack/import-map';\nimport { findResolveMapEntry } from '@ms-cloudpack/package-utilities';\nimport { normalizeRelativePath, slash } from '@ms-cloudpack/path-string-parsing';\nimport path from 'path';\nimport type { BundleServerOptions } from './types/BundleServerOptions.js';\nimport { handleWorker } from './handleWorker.js';\nimport { getLinkedPackageRedirectUrl } from './getLinkedPackageRedirectUrl.js';\nimport { logResponse, sendErrorResponse } from './responseHelpers.js';\n\n/** File read errors have a `code` like `ENOENT`. HTTP errors from `sendFile` have a `statusCode`. */\ntype ErrorWithCodes = Error & { statusCode?: number; code?: string };\n\nconst maxAge = 31536000; // 1 year\n\nexport async function handleBundleRequest(\n options: BundleServerOptions & {\n req: Request;\n res: Response;\n },\n context: Context,\n): Promise<void> {\n const { req, res, disableCache } = options;\n const { session, packageHashes, bus, telemetryClient } = context;\n const { resolveMap, config, linkedPaths } = session;\n const { features = {} } = config;\n const requestPath = slash(req.path.substring(1));\n const force = req.query.force !== undefined;\n const worker = req.query.worker !== undefined;\n const { packageName, version, hash, bundled, filePath, missing } = parseRequestInfo(requestPath);\n\n console.debug(`Bundle request: ${requestPath}`);\n\n // If the package is missing, invalid arguments.\n if (!requestPath || !packageName) {\n return sendErrorResponse({\n res,\n status: 400,\n requestPath,\n message: `Requests must be in the format \"/{packageName}@{version}/{type}/path/file.ext\"`,\n });\n }\n\n const packageEntry = findResolveMapEntry({ packageName, version, resolveMap });\n if (!packageEntry) {\n // If the package is missing, invalid arguments.\n return sendErrorResponse({\n res,\n status: 404,\n requestPath,\n message: `Unrecognized package \"${packageName}@${version || '(unknown)'}\"`,\n });\n }\n\n // This is a hot path, so doing a quick check first.\n if (linkedPaths.length) {\n // Try to redirect to remote host if necessary.\n const redirectUrl = getLinkedPackageRedirectUrl({\n linkedPaths,\n packageName,\n version,\n packageEntry,\n originalUrl: req.originalUrl,\n });\n\n if (redirectUrl) {\n return sendRedirect({ res, requestPath, message: `Redirecting to linked package ${redirectUrl}`, redirectUrl });\n }\n }\n\n // If the version is missing, redirect to the primary version.\n if (!version) {\n return sendRedirect({\n res,\n requestPath,\n message: `Redirecting versionless request to primary version ${packageEntry.version}`,\n redirectUrl: `/${packageName}@${packageEntry.version}${filePath}`,\n });\n }\n\n const packageRequestPath = `${packageName}@${version}${filePath}`;\n\n if (missing && features.autoUpdateEntries) {\n // Exports map for this package is missing, so try adding an override for the requested file.\n const addedPackageOverride = await addPackageOverride({\n input: { packageName, version, importPath: filePath, initiatedBy: 'autoUpdateEntries' },\n ctx: context,\n });\n\n if (addedPackageOverride) {\n // The requested file exists. Trigger a re-bundle to ensure there is no stale cache.\n await ensurePackageBundled(\n {\n name: packageName,\n version,\n shouldForce: true,\n shouldRerun: true,\n disableCache,\n },\n context,\n );\n // This will never be seen by the user, but it is needed to satisfy the response type.\n res.status(202).type('application/javascript').send('');\n return;\n }\n\n // If no entry was added, the import path could not resolve to a file in the package.\n const message = `Failed to resolve module specifier \"${packageRequestPath}\".`;\n // We need to pass the error to the bus so that it can be displayed in the UI,\n // and notify the user when autoUpdateEntries is enabled.\n bus.publish(errorEntrySource, message);\n return sendErrorResponse({ res, status: 404, requestPath, message });\n }\n\n // If we are accessing a non-bundled asset, return the file directly.\n if (!bundled) {\n return sendFile({\n res,\n fileFullPath: path.join(packageEntry.path, filePath),\n requestPath: packageRequestPath,\n parentPath: packageEntry.path,\n isBundled: false,\n shouldCache: !!packageEntry.isExternal,\n });\n }\n\n console.debug(`Bundle request: bundling \"${packageName}@${version}\"`);\n const { result } = await ensurePackageBundled(\n {\n name: packageName,\n version,\n shouldForce: force,\n shouldRerun: force,\n shouldWatch: config.mode !== 'production', // Only watch in non-production modes.\n disableCache,\n },\n context,\n );\n\n if (result.errors?.length || !result.outputPath) {\n // Bundling errors will be logged by ensurePackageBundled on bundle task completion.\n // The only case where they wouldn't be logged is if the user manually refreshes the page and\n // the same failed bundle task result is reused. There's not an easy way to detect that condition\n // (and the overlay and response details will show the error regardless), so only do a debug log\n // to avoid extra noise in the more common case.\n logResponse({\n status: 500,\n requestPath: packageRequestPath,\n message: 'Bundling failed (see error overlay or response data)',\n level: 'debug',\n });\n res.status(500).type('json').send(result);\n return;\n }\n\n // If the worker query param is not set but the file is a worker, handle it.\n if (\n features.enableModuleWorkers &&\n !worker &&\n // Currently, only webpack and rspack setup isWorker in the result.\n result.outputFiles?.find((file) => file.isWorker && file.outputPath === normalizeRelativePath(filePath))\n ) {\n await handleWorker({ req, res }, context);\n return;\n }\n\n sendFile({\n res,\n fileFullPath: path.join(result.outputPath, filePath),\n requestPath: packageRequestPath,\n parentPath: result.outputPath,\n isBundled: true,\n shouldCache:\n result.isExternal ||\n (hash !== 'pending' &&\n // For internal packages, cache if the request hash matches the current source hash\n hash ===\n (await packageHashes.get({\n packagePath: packageEntry.path,\n isSourceHashingEnabled: true,\n targetEnvironment: 'browser',\n }))),\n onError: (err) => {\n // This is a workaround for the browser cache issue.\n // It seems to happen when a file is cached in the browser but the imported files are not cached and not on disk.\n // Increase the target version to clear browser cache for that specific package.\n session.incrementTargetVersion(packageEntry.path);\n\n // If the file is not found, we need to report it to telemetry.\n void telemetryClient.tracer.startActiveSpan('FILE_SERVE_ERROR', (span) => {\n span.setAttributes({\n isCacheHit: !!result.bundleSource && result.bundleSource !== 'bundler',\n isExternal: result.isExternal,\n packageName,\n packageVersion: version,\n bundleSource: result?.bundleSource,\n bundler: result?.bundler,\n bundlerVersion: result?.bundlerVersion,\n filePath,\n request: requestPath,\n hash: result.hash,\n // Actual FS errors will have a `code`, which is more informative than `statusCode`.\n // If `sendFile` manually returns an HTTP error, only `statusCode` is set.\n errorCode: String(err.code || err.statusCode || ''),\n });\n });\n },\n });\n}\n\n/** Debug log about the redirect and then send it */\nfunction sendRedirect(params: { res: Response; requestPath: string; message: string; redirectUrl: string }): void {\n const { res, requestPath, message, redirectUrl } = params;\n logResponse({ status: 302, requestPath, message });\n res.redirect(redirectUrl);\n}\n\n/**\n * Do some error checks, then send the file.\n */\nfunction sendFile(params: {\n res: Response;\n /** Output path for bundled files, package path for unbundled files */\n parentPath: string;\n /** Full path to the file to return */\n fileFullPath: string;\n requestPath: string;\n isBundled: boolean;\n shouldCache: boolean;\n /** Extra error handling such as telemetry */\n onError?: (err: ErrorWithCodes) => void;\n}): void {\n const { res, fileFullPath, requestPath, parentPath, isBundled, shouldCache, onError } = params;\n\n // If the file path is outside of the package, return a 403 error.\n // This is a security measure to prevent access to files outside of the package.\n // (On Windows, path.relative() returns an absolute path for different drives.)\n const relativePath = path.relative(parentPath, fileFullPath);\n if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n sendErrorResponse({\n res,\n status: 403,\n requestPath,\n message: `Resolved file path is outside of the package`,\n consoleMessage: `File resolved to \"${fileFullPath}\" which is outside of \"${parentPath}\"`,\n });\n return;\n }\n\n console.debug(`Bundle response: ${isBundled ? 'bundled' : 'unbundled'} file \"${requestPath}\"`);\n\n // The below header is need to be able to track the browser cache hit ratio.\n res.setHeader('Timing-Allow-Origin', '*');\n\n // Express v5 default behavior is to ignore (404) anything with a leading dot in any path segment,\n // such as .cloudpack, so we have to explicitly allow it.\n res.sendFile(fileFullPath, { dotfiles: 'allow', maxAge: shouldCache ? maxAge : 0 }, (err) => {\n const errWithCode = err as ErrorWithCodes | undefined;\n // It appears this callback is called on success (even though the types don't indicate that),\n // so only continue if there's an error. Also ignore ECONNABORTED errors (don't log to console\n // or telemetry) since this probably means the user refreshed or closed the tab.\n if (!errWithCode || errWithCode.code === 'ECONNABORTED') {\n return;\n }\n\n // Send to telemetry if applicable\n onError?.(errWithCode);\n\n const status = errWithCode.statusCode || 500;\n let message = `Error serving file: ${errWithCode.message}`;\n\n if (errWithCode.code === 'ENOENT') {\n // If it's an actual file not found error (not something else where sendFile manually returns 404),\n // use a custom message since often it's due to a stale cache.\n message =\n `Request resolved to \"${fileFullPath}\" which does not exist. ` +\n 'This might be due to an outdated browser cache, so please try reloading the page (or report the issue if it persists).';\n }\n\n sendErrorResponse({\n res,\n status,\n requestPath,\n message,\n consoleDetails: err.stack && `Bundle request error details: ${err.stack}`,\n });\n });\n}\n"]}
1
+ {"version":3,"file":"handleBundleRequest.js","sourceRoot":"","sources":["../src/handleBundleRequest.ts"],"names":[],"mappings":"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","sourcesContent":["import { ensurePackageBundled, addPackageOverride, errorEntrySource, type Context } from '@ms-cloudpack/api-server';\nimport type { Request, Response } from '@ms-cloudpack/create-express-app';\nimport { parseRequestInfo } from '@ms-cloudpack/import-map';\nimport { findResolveMapEntry } from '@ms-cloudpack/package-utilities';\nimport { normalizeRelativePath, slash } from '@ms-cloudpack/path-string-parsing';\nimport path from 'path';\nimport type { BundleServerOptions } from './types/BundleServerOptions.js';\nimport { handleWorker } from './handleWorker.js';\nimport { rewriteImportsFromFile } from './rewriteImports.js';\nimport { getLinkedPackageRedirectUrl } from './getLinkedPackageRedirectUrl.js';\nimport { logResponse, sendErrorResponse } from './responseHelpers.js';\n\n/** File read errors have a `code` like `ENOENT`. HTTP errors from `sendFile` have a `statusCode`. */\ntype ErrorWithCodes = Error & { statusCode?: number; code?: string };\n\nconst maxAge = 31536000; // 1 year\n\nexport async function handleBundleRequest(\n options: BundleServerOptions & {\n req: Request;\n res: Response;\n },\n context: Context,\n): Promise<void> {\n const { req, res, disableCache } = options;\n const { session, packageHashes, bus, telemetryClient } = context;\n const { resolveMap, config, linkedPaths } = session;\n const { features = {} } = config;\n const requestPath = slash(req.path.substring(1));\n const force = req.query.force !== undefined;\n const worker = req.query.worker !== undefined;\n const { packageName, version, hash, bundled, filePath, missing } = parseRequestInfo(requestPath);\n\n console.debug(`Bundle request: ${requestPath}`);\n\n // If the package is missing, invalid arguments.\n if (!requestPath || !packageName) {\n return sendErrorResponse({\n res,\n status: 400,\n requestPath,\n message: `Requests must be in the format \"/{packageName}@{version}/{type}/path/file.ext\"`,\n });\n }\n\n const packageEntry = findResolveMapEntry({ packageName, version, resolveMap });\n if (!packageEntry) {\n // If the package is missing, invalid arguments.\n return sendErrorResponse({\n res,\n status: 404,\n requestPath,\n message: `Unrecognized package \"${packageName}@${version || '(unknown)'}\"`,\n });\n }\n\n // This is a hot path, so doing a quick check first.\n if (linkedPaths.length) {\n // Try to redirect to remote host if necessary.\n const redirectUrl = getLinkedPackageRedirectUrl({\n linkedPaths,\n packageName,\n version,\n packageEntry,\n originalUrl: req.originalUrl,\n });\n\n if (redirectUrl) {\n return sendRedirect({ res, requestPath, message: `Redirecting to linked package ${redirectUrl}`, redirectUrl });\n }\n }\n\n // If the version is missing, redirect to the primary version.\n if (!version) {\n return sendRedirect({\n res,\n requestPath,\n message: `Redirecting versionless request to primary version ${packageEntry.version}`,\n redirectUrl: `/${packageName}@${packageEntry.version}${filePath}`,\n });\n }\n\n const packageRequestPath = `${packageName}@${version}${filePath}`;\n\n if (missing && features.autoUpdateEntries) {\n // Exports map for this package is missing, so try adding an override for the requested file.\n const addedPackageOverride = await addPackageOverride({\n input: { packageName, version, importPath: filePath, initiatedBy: 'autoUpdateEntries' },\n ctx: context,\n });\n\n if (addedPackageOverride) {\n // The requested file exists. Trigger a re-bundle to ensure there is no stale cache.\n await ensurePackageBundled(\n {\n name: packageName,\n version,\n shouldForce: true,\n shouldRerun: true,\n disableCache,\n },\n context,\n );\n // This will never be seen by the user, but it is needed to satisfy the response type.\n res.status(202).type('application/javascript').send('');\n return;\n }\n\n // If no entry was added, the import path could not resolve to a file in the package.\n const message = `Failed to resolve module specifier \"${packageRequestPath}\".`;\n // We need to pass the error to the bus so that it can be displayed in the UI,\n // and notify the user when autoUpdateEntries is enabled.\n bus.publish(errorEntrySource, message);\n return sendErrorResponse({ res, status: 404, requestPath, message });\n }\n\n // If we are accessing a non-bundled asset, return the file directly.\n if (!bundled) {\n return sendFile({\n res,\n fileFullPath: path.join(packageEntry.path, filePath),\n requestPath: packageRequestPath,\n parentPath: packageEntry.path,\n isBundled: false,\n shouldCache: !!packageEntry.isExternal,\n });\n }\n\n console.debug(`Bundle request: bundling \"${packageName}@${version}\"`);\n const { result } = await ensurePackageBundled(\n {\n name: packageName,\n version,\n shouldForce: force,\n shouldRerun: force,\n shouldWatch: config.mode !== 'production', // Only watch in non-production modes.\n disableCache,\n },\n context,\n );\n\n if (result.errors?.length || !result.outputPath) {\n // Bundling errors will be logged by ensurePackageBundled on bundle task completion.\n // The only case where they wouldn't be logged is if the user manually refreshes the page and\n // the same failed bundle task result is reused. There's not an easy way to detect that condition\n // (and the overlay and response details will show the error regardless), so only do a debug log\n // to avoid extra noise in the more common case.\n logResponse({\n status: 500,\n requestPath: packageRequestPath,\n message: 'Bundling failed (see error overlay or response data)',\n level: 'debug',\n });\n res.status(500).type('json').send(result);\n return;\n }\n\n // If the worker query param is not set but the file is a worker, handle it.\n if (\n features.enableModuleWorkers &&\n !worker &&\n // Currently, only webpack and rspack setup isWorker in the result.\n result.outputFiles?.find((file) => file.isWorker && file.outputPath === normalizeRelativePath(filePath))\n ) {\n await handleWorker(\n {\n req,\n res,\n workerFilePath: path.join(result.outputPath, filePath),\n },\n context,\n );\n return;\n }\n\n const fileFullPath = path.join(result.outputPath, filePath);\n\n // If rewriteImports query param is set, rewrite bare imports in the file\n // This is used for files imported by workers to ensure nested imports also work\n if (req.query.rewriteimports !== undefined && session.importMap) {\n try {\n const rewrittenSource = await rewriteImportsFromFile(fileFullPath, context);\n\n logResponse({ status: 200, requestPath: packageRequestPath, message: 'Returning file with rewritten imports' });\n // Do not cache these responses as they are based on the import map at request time.\n res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');\n res.type('text/javascript').send(rewrittenSource);\n return;\n } catch (err) {\n const error = err as Error;\n console.error('Failed to rewrite imports for', packageRequestPath, ':', error);\n return sendErrorResponse({\n res,\n status: 500,\n requestPath: packageRequestPath,\n message: `Failed to rewrite imports: ${error.message}`,\n });\n }\n }\n\n sendFile({\n res,\n fileFullPath,\n requestPath: packageRequestPath,\n parentPath: result.outputPath,\n isBundled: true,\n shouldCache:\n result.isExternal ||\n (hash !== 'pending' &&\n // For internal packages, cache if the request hash matches the current source hash\n hash ===\n (await packageHashes.get({\n packagePath: packageEntry.path,\n isSourceHashingEnabled: true,\n targetEnvironment: 'browser',\n }))),\n onError: (err) => {\n // This is a workaround for the browser cache issue.\n // It seems to happen when a file is cached in the browser but the imported files are not cached and not on disk.\n // Increase the target version to clear browser cache for that specific package.\n session.incrementTargetVersion(packageEntry.path);\n\n // If the file is not found, we need to report it to telemetry.\n void telemetryClient.tracer.startActiveSpan('FILE_SERVE_ERROR', (span) => {\n span.setAttributes({\n isCacheHit: !!result.bundleSource && result.bundleSource !== 'bundler',\n isExternal: result.isExternal,\n packageName,\n packageVersion: version,\n bundleSource: result?.bundleSource,\n bundler: result?.bundler,\n bundlerVersion: result?.bundlerVersion,\n filePath,\n request: requestPath,\n hash: result.hash,\n // Actual FS errors will have a `code`, which is more informative than `statusCode`.\n // If `sendFile` manually returns an HTTP error, only `statusCode` is set.\n errorCode: String(err.code || err.statusCode || ''),\n });\n });\n },\n });\n}\n\n/** Debug log about the redirect and then send it */\nfunction sendRedirect(params: { res: Response; requestPath: string; message: string; redirectUrl: string }): void {\n const { res, requestPath, message, redirectUrl } = params;\n logResponse({ status: 302, requestPath, message });\n res.redirect(redirectUrl);\n}\n\n/**\n * Do some error checks, then send the file.\n */\nfunction sendFile(params: {\n res: Response;\n /** Output path for bundled files, package path for unbundled files */\n parentPath: string;\n /** Full path to the file to return */\n fileFullPath: string;\n requestPath: string;\n isBundled: boolean;\n shouldCache: boolean;\n /** Extra error handling such as telemetry */\n onError?: (err: ErrorWithCodes) => void;\n}): void {\n const { res, fileFullPath, requestPath, parentPath, isBundled, shouldCache, onError } = params;\n\n // If the file path is outside of the package, return a 403 error.\n // This is a security measure to prevent access to files outside of the package.\n // (On Windows, path.relative() returns an absolute path for different drives.)\n const relativePath = path.relative(parentPath, fileFullPath);\n if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n sendErrorResponse({\n res,\n status: 403,\n requestPath,\n message: `Resolved file path is outside of the package`,\n consoleMessage: `File resolved to \"${fileFullPath}\" which is outside of \"${parentPath}\"`,\n });\n return;\n }\n\n console.debug(`Bundle response: ${isBundled ? 'bundled' : 'unbundled'} file \"${requestPath}\"`);\n\n // The below header is need to be able to track the browser cache hit ratio.\n res.setHeader('Timing-Allow-Origin', '*');\n\n // Express v5 default behavior is to ignore (404) anything with a leading dot in any path segment,\n // such as .cloudpack, so we have to explicitly allow it.\n res.sendFile(fileFullPath, { dotfiles: 'allow', maxAge: shouldCache ? maxAge : 0 }, (err) => {\n const errWithCode = err as ErrorWithCodes | undefined;\n // It appears this callback is called on success (even though the types don't indicate that),\n // so only continue if there's an error. Also ignore ECONNABORTED errors (don't log to console\n // or telemetry) since this probably means the user refreshed or closed the tab.\n if (!errWithCode || errWithCode.code === 'ECONNABORTED') {\n return;\n }\n\n // Send to telemetry if applicable\n onError?.(errWithCode);\n\n const status = errWithCode.statusCode || 500;\n let message = `Error serving file: ${errWithCode.message}`;\n\n if (errWithCode.code === 'ENOENT') {\n // If it's an actual file not found error (not something else where sendFile manually returns 404),\n // use a custom message since often it's due to a stale cache.\n message =\n `Request resolved to \"${fileFullPath}\" which does not exist. ` +\n 'This might be due to an outdated browser cache, so please try reloading the page (or report the issue if it persists).';\n }\n\n sendErrorResponse({\n res,\n status,\n requestPath,\n message,\n consoleDetails: err.stack && `Bundle request error details: ${err.stack}`,\n });\n });\n}\n"]}
@@ -1,18 +1,23 @@
1
1
  import type { PartialContext } from '@ms-cloudpack/api-server';
2
2
  import type { Request, Response } from '@ms-cloudpack/create-express-app';
3
3
  /**
4
- * The function handles a worker request by shimming import maps, a global object and process.browser
5
- * It also adds the worker query parameter so the bundle server knows it has been shimmed,
6
- * while preserving other query parameters
4
+ * The function handles a worker request by either:
5
+ * 1. Rewriting bare imports to use import map URLs (when rewriteWorkerImports is enabled)
6
+ * 2. Shimming import maps using es-module-shims (fallback approach)
7
+ *
8
+ * It also adds the worker query parameter so the bundle server knows it has been handled,
9
+ * while preserving other query parameters.
7
10
  *
8
11
  * It is called when the feature `enableModuleWorkers` is enabled, the worker has not been handled yet,
9
12
  * and the output file is a worker.
10
13
  *
11
14
  * This works even for workers that are not in the import map, as long as they are in the bundle. It also works
12
- * when the worker is requested through a blob as the the request goes through the bundle server.
15
+ * when the worker is requested through a blob as the request goes through the bundle server.
13
16
  */
14
17
  export declare function handleWorker(options: {
15
18
  req: Request;
16
19
  res: Response;
20
+ /** The worker file path to read */
21
+ workerFilePath?: string;
17
22
  }, context: PartialContext<'session', 'importMap' | 'urls' | 'config'>): Promise<void>;
18
23
  //# sourceMappingURL=handleWorker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handleWorker.d.ts","sourceRoot":"","sources":["../src/handleWorker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAc1E;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE;IACP,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;CACf,EACD,OAAO,EAAE,cAAc,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC,GAClE,OAAO,CAAC,IAAI,CAAC,CAsFf"}
1
+ {"version":3,"file":"handleWorker.d.ts","sourceRoot":"","sources":["../src/handleWorker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAe1E;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE;IACP,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;IACd,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,EACD,OAAO,EAAE,cAAc,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC,GAClE,OAAO,CAAC,IAAI,CAAC,CA6Ff"}
@@ -7,22 +7,32 @@ import fsPromises from 'fs/promises';
7
7
  import { getInlineScript } from '@ms-cloudpack/inline-scripts';
8
8
  import { reduceResourceUrl } from '@ms-cloudpack/import-map';
9
9
  import { logResponse, sendErrorResponse } from './responseHelpers.js';
10
+ import { rewriteImportsFromFile } from './rewriteImports.js';
10
11
  const filename = fileURLToPath(import.meta.url);
11
12
  let esModuleShim;
12
13
  /**
13
- * The function handles a worker request by shimming import maps, a global object and process.browser
14
- * It also adds the worker query parameter so the bundle server knows it has been shimmed,
15
- * while preserving other query parameters
14
+ * The function handles a worker request by either:
15
+ * 1. Rewriting bare imports to use import map URLs (when rewriteWorkerImports is enabled)
16
+ * 2. Shimming import maps using es-module-shims (fallback approach)
17
+ *
18
+ * It also adds the worker query parameter so the bundle server knows it has been handled,
19
+ * while preserving other query parameters.
16
20
  *
17
21
  * It is called when the feature `enableModuleWorkers` is enabled, the worker has not been handled yet,
18
22
  * and the output file is a worker.
19
23
  *
20
24
  * This works even for workers that are not in the import map, as long as they are in the bundle. It also works
21
- * when the worker is requested through a blob as the the request goes through the bundle server.
25
+ * when the worker is requested through a blob as the request goes through the bundle server.
22
26
  */
23
27
  export async function handleWorker(options, context) {
24
- const { req, res } = options;
28
+ const { req, res, workerFilePath } = options;
25
29
  const { session } = context;
30
+ const { features = {} } = session.config;
31
+ // Check if we should use the new import rewriting approach
32
+ if (features.rewriteWorkerImports && workerFilePath) {
33
+ return handleWorkerWithRewrite({ req, res, workerFilePath }, context);
34
+ }
35
+ // Fallback to es-module-shims approach
26
36
  esModuleShim ??= await getShim();
27
37
  if (!esModuleShim) {
28
38
  // If we can't get the shim, we can't handle the worker request
@@ -103,6 +113,60 @@ export async function handleWorker(options, context) {
103
113
  // namely the `es-module-shim.wasm.js` output: es-module-shims/dist/es-module-shims.wasm.js
104
114
  const esModuleShimsPackage = 'es-module-shims';
105
115
  const esModuleShimsFile = 'dist/es-module-shims.wasm.js';
116
+ /**
117
+ * Handles a worker request by rewriting bare imports to use import map URLs.
118
+ * This approach doesn't require es-module-shims and works with service workers.
119
+ */
120
+ async function handleWorkerWithRewrite(options, context) {
121
+ const { req, res, workerFilePath } = options;
122
+ const { session } = context;
123
+ console.debug(`Handling worker request with import rewriting for ${req.path}`);
124
+ try {
125
+ const rewrittenSource = await rewriteImportsFromFile(workerFilePath, context);
126
+ // Inject define flags (like process.browser) at the top - only needed for worker entry points
127
+ const defineScript = await getInlineScript('defineProcess');
128
+ const registerDefineFlags = await getInlineScript('registerDefineFlags');
129
+ const defineInjection = dedent `
130
+ // Shim the global object in workers
131
+ var globalObject =
132
+ typeof globalThis !== 'undefined'
133
+ ? globalThis
134
+ : typeof self !== 'undefined'
135
+ ? self
136
+ : typeof window !== 'undefined'
137
+ ? window
138
+ : typeof global !== 'undefined'
139
+ ? global
140
+ : {};
141
+ var window = globalObject;
142
+
143
+ ${defineScript}
144
+
145
+ ${registerDefineFlags}
146
+
147
+ registerDefineFlags(window, ${JSON.stringify(session.config.define ?? {})});
148
+
149
+ `;
150
+ const finalSource = defineInjection + rewrittenSource;
151
+ logResponse({ status: 200, requestPath: req.path, message: 'Returning worker with rewritten imports' });
152
+ // For service workers, we need to set the Service-Worker-Allowed header to allow scope "/"
153
+ // This is not the default behavior, which restricts the scope to the worker's directory
154
+ res.setHeader('Service-Worker-Allowed', '/');
155
+ // Do not cache these responses as they are based on the import map at request time.
156
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
157
+ res.type('text/javascript').send(finalSource);
158
+ }
159
+ catch (err) {
160
+ const error = err;
161
+ console.error('Failed to rewrite worker imports for', req.path + ':', error);
162
+ return sendErrorResponse({
163
+ res,
164
+ status: 500,
165
+ requestPath: req.path,
166
+ message: `Failed to rewrite worker imports: ${error.message}`,
167
+ });
168
+ }
169
+ }
106
170
  /** Get the `es-module-shims` WASM build file contents */
107
171
  async function getShim() {
108
172
  const esModuleShimsPath = await resolve(esModuleShimsPackage, filename);
@@ -1 +1 @@
1
- {"version":3,"file":"handleWorker.js","sourceRoot":"","sources":["../src/handleWorker.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PartialContext } from '@ms-cloudpack/api-server';\nimport type { Request, Response } from '@ms-cloudpack/create-express-app';\nimport { makeUrl } from '@ms-cloudpack/path-string-parsing';\nimport { dedent } from 'ts-dedent';\nimport { resolve } from '@ms-cloudpack/path-utilities';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport fsPromises from 'fs/promises';\nimport { getInlineScript } from '@ms-cloudpack/inline-scripts';\nimport { reduceResourceUrl } from '@ms-cloudpack/import-map';\nimport { logResponse, sendErrorResponse } from './responseHelpers.js';\n\nconst filename = fileURLToPath(import.meta.url);\nlet esModuleShim: string | undefined;\n\n/**\n * The function handles a worker request by shimming import maps, a global object and process.browser\n * It also adds the worker query parameter so the bundle server knows it has been shimmed,\n * while preserving other query parameters\n *\n * It is called when the feature `enableModuleWorkers` is enabled, the worker has not been handled yet,\n * and the output file is a worker.\n *\n * This works even for workers that are not in the import map, as long as they are in the bundle. It also works\n * when the worker is requested through a blob as the the request goes through the bundle server.\n */\nexport async function handleWorker(\n options: {\n req: Request;\n res: Response;\n },\n context: PartialContext<'session', 'importMap' | 'urls' | 'config'>,\n): Promise<void> {\n const { req, res } = options;\n const { session } = context;\n\n esModuleShim ??= await getShim();\n\n if (!esModuleShim) {\n // If we can't get the shim, we can't handle the worker request\n return sendErrorResponse({\n res,\n status: 500,\n requestPath: req.path,\n message: 'Failed to load import map shim for worker',\n });\n }\n\n const { relativeImportMapPaths } = session.config.features ?? {};\n const appUrl = relativeImportMapPaths ? session.urls.appServer : undefined;\n\n const originalUrl = makeUrl(req.url, session.urls.bundleServer);\n // Add the worker query parameter so the bundle server knows it has ben shimmed\n originalUrl.searchParams.set('worker', 'shim');\n\n // Convert to relative path if relativeImportMapPaths is enabled\n const workerUrl = reduceResourceUrl(originalUrl, appUrl);\n\n console.debug(`Handling worker request for ${req.path}, shimmed url: ${workerUrl}`);\n\n logResponse({ status: 200, requestPath: req.path, message: 'Returning worker shim' });\n\n // The following code is based on https://github.com/guybedford/es-module-shims?tab=readme-ov-file#module-workers\n // but it uses the bundle server to avoid sending a blob and to preserve url parameters\n // it also shims the global object and process.browser for compatibility with some packages\n // We also need to set up web worker and shared worker temporary handlers right away\n // to receive messages from the main thread\n // This is necessary as there is a bug in the browser that when the handlers are\n // set up inside an async function the messages are not received.\n // In this case importShim is an async function.\n res.type('text/javascript').send(dedent`\n var pending = true;\n var messageQueue = [];\n self.onmessage = function (event) {\n if (pending) {\n messageQueue.push(event);\n }\n };\n self.onconnect = function (event) {\n if (pending) {\n messageQueue.push(event);\n }\n };\n\n // Shim the global object in workers\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n var window = globalObject;\n\n ${await getInlineScript('defineProcess')}\n\n ${await getInlineScript('registerDefineFlags')}\n\n registerDefineFlags(window, ${JSON.stringify(session.config.define ?? {})});\n\n globalObject.esmsInitOptions = { shimMode: true };\n ${esModuleShim}\n importShim.addImportMap(${JSON.stringify(session.importMap)});\n importShim('${workerUrl}')\n .then(() => {\n pending = false;\n // Process the message queue\n while (messageQueue.length) {\n const message = messageQueue.shift();\n self.onmessage(message);\n self.onconnect(message);\n }\n })\n .catch(e => setTimeout(() => { throw e; }));\n `);\n}\n\n// esModuleShims must point to the non-CSP build of ES Module Shims,\n// namely the `es-module-shim.wasm.js` output: es-module-shims/dist/es-module-shims.wasm.js\nconst esModuleShimsPackage = 'es-module-shims';\nconst esModuleShimsFile = 'dist/es-module-shims.wasm.js';\n\n/** Get the `es-module-shims` WASM build file contents */\nasync function getShim(): Promise<string | undefined> {\n const esModuleShimsPath = await resolve(esModuleShimsPackage, filename);\n if (!esModuleShimsPath) {\n return;\n }\n const esModuleShimsWasm = path.join(esModuleShimsPath, esModuleShimsFile);\n try {\n return await fsPromises.readFile(esModuleShimsWasm, 'utf8');\n } catch {\n // ignore\n }\n}\n"]}
1
+ {"version":3,"file":"handleWorker.js","sourceRoot":"","sources":["../src/handleWorker.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PartialContext } from '@ms-cloudpack/api-server';\nimport type { Request, Response } from '@ms-cloudpack/create-express-app';\nimport { makeUrl } from '@ms-cloudpack/path-string-parsing';\nimport { dedent } from 'ts-dedent';\nimport { resolve } from '@ms-cloudpack/path-utilities';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport fsPromises from 'fs/promises';\nimport { getInlineScript } from '@ms-cloudpack/inline-scripts';\nimport { reduceResourceUrl } from '@ms-cloudpack/import-map';\nimport { logResponse, sendErrorResponse } from './responseHelpers.js';\nimport { rewriteImportsFromFile } from './rewriteImports.js';\n\nconst filename = fileURLToPath(import.meta.url);\nlet esModuleShim: string | undefined;\n\n/**\n * The function handles a worker request by either:\n * 1. Rewriting bare imports to use import map URLs (when rewriteWorkerImports is enabled)\n * 2. Shimming import maps using es-module-shims (fallback approach)\n *\n * It also adds the worker query parameter so the bundle server knows it has been handled,\n * while preserving other query parameters.\n *\n * It is called when the feature `enableModuleWorkers` is enabled, the worker has not been handled yet,\n * and the output file is a worker.\n *\n * This works even for workers that are not in the import map, as long as they are in the bundle. It also works\n * when the worker is requested through a blob as the request goes through the bundle server.\n */\nexport async function handleWorker(\n options: {\n req: Request;\n res: Response;\n /** The worker file path to read */\n workerFilePath?: string;\n },\n context: PartialContext<'session', 'importMap' | 'urls' | 'config'>,\n): Promise<void> {\n const { req, res, workerFilePath } = options;\n const { session } = context;\n const { features = {} } = session.config;\n\n // Check if we should use the new import rewriting approach\n if (features.rewriteWorkerImports && workerFilePath) {\n return handleWorkerWithRewrite({ req, res, workerFilePath }, context);\n }\n\n // Fallback to es-module-shims approach\n esModuleShim ??= await getShim();\n\n if (!esModuleShim) {\n // If we can't get the shim, we can't handle the worker request\n return sendErrorResponse({\n res,\n status: 500,\n requestPath: req.path,\n message: 'Failed to load import map shim for worker',\n });\n }\n\n const { relativeImportMapPaths } = session.config.features ?? {};\n const appUrl = relativeImportMapPaths ? session.urls.appServer : undefined;\n\n const originalUrl = makeUrl(req.url, session.urls.bundleServer);\n // Add the worker query parameter so the bundle server knows it has ben shimmed\n originalUrl.searchParams.set('worker', 'shim');\n\n // Convert to relative path if relativeImportMapPaths is enabled\n const workerUrl = reduceResourceUrl(originalUrl, appUrl);\n\n console.debug(`Handling worker request for ${req.path}, shimmed url: ${workerUrl}`);\n\n logResponse({ status: 200, requestPath: req.path, message: 'Returning worker shim' });\n\n // The following code is based on https://github.com/guybedford/es-module-shims?tab=readme-ov-file#module-workers\n // but it uses the bundle server to avoid sending a blob and to preserve url parameters\n // it also shims the global object and process.browser for compatibility with some packages\n // We also need to set up web worker and shared worker temporary handlers right away\n // to receive messages from the main thread\n // This is necessary as there is a bug in the browser that when the handlers are\n // set up inside an async function the messages are not received.\n // In this case importShim is an async function.\n res.type('text/javascript').send(dedent`\n var pending = true;\n var messageQueue = [];\n self.onmessage = function (event) {\n if (pending) {\n messageQueue.push(event);\n }\n };\n self.onconnect = function (event) {\n if (pending) {\n messageQueue.push(event);\n }\n };\n\n // Shim the global object in workers\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n var window = globalObject;\n\n ${await getInlineScript('defineProcess')}\n\n ${await getInlineScript('registerDefineFlags')}\n\n registerDefineFlags(window, ${JSON.stringify(session.config.define ?? {})});\n\n globalObject.esmsInitOptions = { shimMode: true };\n ${esModuleShim}\n importShim.addImportMap(${JSON.stringify(session.importMap)});\n importShim('${workerUrl}')\n .then(() => {\n pending = false;\n // Process the message queue\n while (messageQueue.length) {\n const message = messageQueue.shift();\n self.onmessage(message);\n self.onconnect(message);\n }\n })\n .catch(e => setTimeout(() => { throw e; }));\n `);\n}\n\n// esModuleShims must point to the non-CSP build of ES Module Shims,\n// namely the `es-module-shim.wasm.js` output: es-module-shims/dist/es-module-shims.wasm.js\nconst esModuleShimsPackage = 'es-module-shims';\nconst esModuleShimsFile = 'dist/es-module-shims.wasm.js';\n\n/**\n * Handles a worker request by rewriting bare imports to use import map URLs.\n * This approach doesn't require es-module-shims and works with service workers.\n */\nasync function handleWorkerWithRewrite(\n options: {\n req: Request;\n res: Response;\n workerFilePath: string;\n },\n context: PartialContext<'session', 'importMap' | 'urls' | 'config'>,\n): Promise<void> {\n const { req, res, workerFilePath } = options;\n const { session } = context;\n\n console.debug(`Handling worker request with import rewriting for ${req.path}`);\n\n try {\n const rewrittenSource = await rewriteImportsFromFile(workerFilePath, context);\n\n // Inject define flags (like process.browser) at the top - only needed for worker entry points\n const defineScript = await getInlineScript('defineProcess');\n const registerDefineFlags = await getInlineScript('registerDefineFlags');\n const defineInjection = dedent`\n // Shim the global object in workers\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n var window = globalObject;\n\n ${defineScript}\n\n ${registerDefineFlags}\n\n registerDefineFlags(window, ${JSON.stringify(session.config.define ?? {})});\n\n `;\n\n const finalSource = defineInjection + rewrittenSource;\n\n logResponse({ status: 200, requestPath: req.path, message: 'Returning worker with rewritten imports' });\n\n // For service workers, we need to set the Service-Worker-Allowed header to allow scope \"/\"\n // This is not the default behavior, which restricts the scope to the worker's directory\n res.setHeader('Service-Worker-Allowed', '/');\n // Do not cache these responses as they are based on the import map at request time.\n res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');\n res.type('text/javascript').send(finalSource);\n } catch (err) {\n const error = err as Error;\n console.error('Failed to rewrite worker imports for', req.path + ':', error);\n return sendErrorResponse({\n res,\n status: 500,\n requestPath: req.path,\n message: `Failed to rewrite worker imports: ${error.message}`,\n });\n }\n}\n\n/** Get the `es-module-shims` WASM build file contents */\nasync function getShim(): Promise<string | undefined> {\n const esModuleShimsPath = await resolve(esModuleShimsPackage, filename);\n if (!esModuleShimsPath) {\n return;\n }\n const esModuleShimsWasm = path.join(esModuleShimsPath, esModuleShimsFile);\n try {\n return await fsPromises.readFile(esModuleShimsWasm, 'utf8');\n } catch {\n // ignore\n }\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import type { ImportMap } from '@ms-cloudpack/import-map';
2
+ import type { PartialContext } from '@ms-cloudpack/api-server';
3
+ /**
4
+ * Rewrites bare module imports in source code to use full URLs from the import map.
5
+ * This allows workers (including service workers) and their dependencies to function without es-module-shims.
6
+ *
7
+ * @param source - The original source code
8
+ * @param importMap - The import map to resolve bare imports against
9
+ * @param bundleServerUrl - The bundle server base URL for resolving relative paths
10
+ * @returns The rewritten source code with all bare imports replaced with full URLs
11
+ */
12
+ export declare function rewriteImports(source: string, importMap: ImportMap, bundleServerUrl?: string): Promise<string>;
13
+ /**
14
+ * Reads a file and rewrites bare imports to use import map URLs.
15
+ * This is used for workers and their nested imports.
16
+ *
17
+ * @param filePath - The file path to read and rewrite
18
+ * @param context - The session context with importMap and config
19
+ * @returns The rewritten source code
20
+ */
21
+ export declare function rewriteImportsFromFile(filePath: string, context: PartialContext<'session', 'importMap' | 'urls' | 'config'>): Promise<string>;
22
+ //# sourceMappingURL=rewriteImports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewriteImports.d.ts","sourceRoot":"","sources":["../src/rewriteImports.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK/D;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6FpH;AA2DD;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC,GAClE,OAAO,CAAC,MAAM,CAAC,CAWjB"}
@@ -0,0 +1,160 @@
1
+ import { init, parse } from 'es-module-lexer';
2
+ import fsPromises from 'fs/promises';
3
+ let initialized = false;
4
+ /**
5
+ * Rewrites bare module imports in source code to use full URLs from the import map.
6
+ * This allows workers (including service workers) and their dependencies to function without es-module-shims.
7
+ *
8
+ * @param source - The original source code
9
+ * @param importMap - The import map to resolve bare imports against
10
+ * @param bundleServerUrl - The bundle server base URL for resolving relative paths
11
+ * @returns The rewritten source code with all bare imports replaced with full URLs
12
+ */
13
+ export async function rewriteImports(source, importMap, bundleServerUrl) {
14
+ if (!initialized) {
15
+ // Await init once for the Web Assembly boot to call parse synchronously.
16
+ await init;
17
+ initialized = true;
18
+ }
19
+ // Parse the source to find all imports
20
+ const [imports] = parse(source);
21
+ // If no imports, return source as-is
22
+ if (imports.length === 0) {
23
+ return source;
24
+ }
25
+ // Build a list of replacements to apply (in reverse order to maintain correct positions)
26
+ const replacements = [];
27
+ for (const imp of imports) {
28
+ // es-module-lexer behavior differs by import type:
29
+ // - Static imports (t === 1): s/e positions EXCLUDE quotes
30
+ // - Dynamic imports (t === 2): s/e positions INCLUDE quotes
31
+ const isDynamicImport = imp.t === 2;
32
+ const importSpecifierRaw = source.substring(imp.s, imp.e);
33
+ const importSpecifier = isDynamicImport
34
+ ? importSpecifierRaw.slice(1, -1) // Strip quotes for dynamic imports
35
+ : importSpecifierRaw; // No stripping for static imports
36
+ // For relative imports, add the rewriteimports query param so nested imports also get rewritten
37
+ if (importSpecifier.startsWith('./') || importSpecifier.startsWith('../')) {
38
+ const separator = importSpecifier.includes('?') ? '&' : '?';
39
+ const rewrittenPath = `${importSpecifier}${separator}rewriteimports=true`;
40
+ replacements.push({
41
+ start: imp.s,
42
+ end: imp.e,
43
+ replacement: isDynamicImport
44
+ ? `${importSpecifierRaw[0]}${rewrittenPath}${importSpecifierRaw[0]}`
45
+ : rewrittenPath,
46
+ });
47
+ continue;
48
+ }
49
+ // Skip absolute URLs that already have the query param or are external
50
+ if (importSpecifier.startsWith('http://') || importSpecifier.startsWith('https://')) {
51
+ continue;
52
+ }
53
+ // For absolute paths (starting with /), add the query param
54
+ if (importSpecifier.startsWith('/')) {
55
+ const separator = importSpecifier.includes('?') ? '&' : '?';
56
+ const rewrittenPath = `${importSpecifier}${separator}rewriteimports=true`;
57
+ replacements.push({
58
+ start: imp.s,
59
+ end: imp.e,
60
+ replacement: isDynamicImport
61
+ ? `${importSpecifierRaw[0]}${rewrittenPath}${importSpecifierRaw[0]}`
62
+ : rewrittenPath,
63
+ });
64
+ continue;
65
+ }
66
+ // This is a bare import - try to resolve it from the import map
67
+ const resolvedUrl = resolveFromImportMap(importSpecifier, importMap, bundleServerUrl);
68
+ if (resolvedUrl) {
69
+ // Append rewriteimports query param so nested imports also get rewritten
70
+ const separator = resolvedUrl.includes('?') ? '&' : '?';
71
+ const urlWithRewrite = `${resolvedUrl}${separator}rewriteimports=true`;
72
+ replacements.push({
73
+ start: imp.s,
74
+ end: imp.e,
75
+ replacement: isDynamicImport
76
+ ? `${importSpecifierRaw[0]}${urlWithRewrite}${importSpecifierRaw[0]}`
77
+ : urlWithRewrite,
78
+ });
79
+ }
80
+ else {
81
+ // If we can't resolve it, log a warning but don't fail
82
+ console.warn(`Could not resolve bare import "${importSpecifier}" in worker. It will remain as-is.`);
83
+ }
84
+ }
85
+ // Apply replacements in reverse order to maintain correct positions
86
+ let rewrittenSource = source;
87
+ for (const replacement of replacements.reverse()) {
88
+ rewrittenSource =
89
+ rewrittenSource.substring(0, replacement.start) +
90
+ replacement.replacement +
91
+ rewrittenSource.substring(replacement.end);
92
+ }
93
+ return rewrittenSource;
94
+ }
95
+ /**
96
+ * Resolves a bare import specifier using the import map.
97
+ *
98
+ * @param specifier - The bare import specifier (e.g., "uuid" or "uuid/v4")
99
+ * @param importMap - The import map to resolve against
100
+ * @param bundleServerUrl - Optional bundle server URL to make paths absolute
101
+ * @returns The resolved URL, or undefined if not found
102
+ */
103
+ function resolveFromImportMap(specifier, importMap, bundleServerUrl) {
104
+ const { imports } = importMap;
105
+ if (!imports) {
106
+ return undefined;
107
+ }
108
+ // First try exact match
109
+ if (imports[specifier]) {
110
+ return makeAbsoluteUrl(imports[specifier], bundleServerUrl);
111
+ }
112
+ // Then try prefix matching (for package subpaths)
113
+ // Import maps support trailing slash patterns like "uuid/" -> "/.../uuid/"
114
+ const matchingKeys = Object.keys(imports)
115
+ .filter((key) => key.endsWith('/') && specifier.startsWith(key))
116
+ .sort((a, b) => b.length - a.length); // Sort by length descending for most specific match
117
+ for (const key of matchingKeys) {
118
+ const replacement = imports[key];
119
+ const subpath = specifier.substring(key.length);
120
+ const resolvedUrl = replacement.endsWith('/') ? replacement + subpath : replacement;
121
+ return makeAbsoluteUrl(resolvedUrl, bundleServerUrl);
122
+ }
123
+ return undefined;
124
+ }
125
+ /**
126
+ * Makes a URL absolute if it's relative and a base URL is provided.
127
+ */
128
+ function makeAbsoluteUrl(url, baseUrl) {
129
+ // Already absolute
130
+ if (url.startsWith('http://') || url.startsWith('https://')) {
131
+ return url;
132
+ }
133
+ // Make absolute using base URL if provided
134
+ if (baseUrl) {
135
+ // Remove trailing slash from base URL
136
+ const cleanBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
137
+ // Ensure URL starts with /
138
+ const cleanUrl = url.startsWith('/') ? url : `/${url}`;
139
+ return `${cleanBase}${cleanUrl}`;
140
+ }
141
+ return url;
142
+ }
143
+ /**
144
+ * Reads a file and rewrites bare imports to use import map URLs.
145
+ * This is used for workers and their nested imports.
146
+ *
147
+ * @param filePath - The file path to read and rewrite
148
+ * @param context - The session context with importMap and config
149
+ * @returns The rewritten source code
150
+ */
151
+ export async function rewriteImportsFromFile(filePath, context) {
152
+ const { session } = context;
153
+ const source = await fsPromises.readFile(filePath, 'utf8');
154
+ if (!session.importMap) {
155
+ throw new Error('Import map is not available');
156
+ }
157
+ const bundleServerUrl = session.config.features?.relativeImportMapPaths ? undefined : session.urls.bundleServer;
158
+ return rewriteImports(source, session.importMap, bundleServerUrl);
159
+ }
160
+ //# sourceMappingURL=rewriteImports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewriteImports.js","sourceRoot":"","sources":["../src/rewriteImports.ts"],"names":[],"mappings":"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","sourcesContent":["import { init, parse } from 'es-module-lexer';\nimport type { ImportMap } from '@ms-cloudpack/import-map';\nimport type { PartialContext } from '@ms-cloudpack/api-server';\nimport fsPromises from 'fs/promises';\n\nlet initialized = false;\n\n/**\n * Rewrites bare module imports in source code to use full URLs from the import map.\n * This allows workers (including service workers) and their dependencies to function without es-module-shims.\n *\n * @param source - The original source code\n * @param importMap - The import map to resolve bare imports against\n * @param bundleServerUrl - The bundle server base URL for resolving relative paths\n * @returns The rewritten source code with all bare imports replaced with full URLs\n */\nexport async function rewriteImports(source: string, importMap: ImportMap, bundleServerUrl?: string): Promise<string> {\n if (!initialized) {\n // Await init once for the Web Assembly boot to call parse synchronously.\n await init;\n initialized = true;\n }\n\n // Parse the source to find all imports\n const [imports] = parse(source);\n\n // If no imports, return source as-is\n if (imports.length === 0) {\n return source;\n }\n\n // Build a list of replacements to apply (in reverse order to maintain correct positions)\n const replacements: Array<{ start: number; end: number; replacement: string }> = [];\n\n for (const imp of imports) {\n // es-module-lexer behavior differs by import type:\n // - Static imports (t === 1): s/e positions EXCLUDE quotes\n // - Dynamic imports (t === 2): s/e positions INCLUDE quotes\n const isDynamicImport = imp.t === 2;\n const importSpecifierRaw = source.substring(imp.s, imp.e);\n\n const importSpecifier = isDynamicImport\n ? importSpecifierRaw.slice(1, -1) // Strip quotes for dynamic imports\n : importSpecifierRaw; // No stripping for static imports\n\n // For relative imports, add the rewriteimports query param so nested imports also get rewritten\n if (importSpecifier.startsWith('./') || importSpecifier.startsWith('../')) {\n const separator = importSpecifier.includes('?') ? '&' : '?';\n const rewrittenPath = `${importSpecifier}${separator}rewriteimports=true`;\n replacements.push({\n start: imp.s,\n end: imp.e,\n replacement: isDynamicImport\n ? `${importSpecifierRaw[0]}${rewrittenPath}${importSpecifierRaw[0]}`\n : rewrittenPath,\n });\n continue;\n }\n\n // Skip absolute URLs that already have the query param or are external\n if (importSpecifier.startsWith('http://') || importSpecifier.startsWith('https://')) {\n continue;\n }\n\n // For absolute paths (starting with /), add the query param\n if (importSpecifier.startsWith('/')) {\n const separator = importSpecifier.includes('?') ? '&' : '?';\n const rewrittenPath = `${importSpecifier}${separator}rewriteimports=true`;\n replacements.push({\n start: imp.s,\n end: imp.e,\n replacement: isDynamicImport\n ? `${importSpecifierRaw[0]}${rewrittenPath}${importSpecifierRaw[0]}`\n : rewrittenPath,\n });\n continue;\n }\n\n // This is a bare import - try to resolve it from the import map\n const resolvedUrl = resolveFromImportMap(importSpecifier, importMap, bundleServerUrl);\n\n if (resolvedUrl) {\n // Append rewriteimports query param so nested imports also get rewritten\n const separator = resolvedUrl.includes('?') ? '&' : '?';\n const urlWithRewrite = `${resolvedUrl}${separator}rewriteimports=true`;\n\n replacements.push({\n start: imp.s,\n end: imp.e,\n replacement: isDynamicImport\n ? `${importSpecifierRaw[0]}${urlWithRewrite}${importSpecifierRaw[0]}`\n : urlWithRewrite,\n });\n } else {\n // If we can't resolve it, log a warning but don't fail\n console.warn(`Could not resolve bare import \"${importSpecifier}\" in worker. It will remain as-is.`);\n }\n }\n\n // Apply replacements in reverse order to maintain correct positions\n let rewrittenSource = source;\n for (const replacement of replacements.reverse()) {\n rewrittenSource =\n rewrittenSource.substring(0, replacement.start) +\n replacement.replacement +\n rewrittenSource.substring(replacement.end);\n }\n\n return rewrittenSource;\n}\n\n/**\n * Resolves a bare import specifier using the import map.\n *\n * @param specifier - The bare import specifier (e.g., \"uuid\" or \"uuid/v4\")\n * @param importMap - The import map to resolve against\n * @param bundleServerUrl - Optional bundle server URL to make paths absolute\n * @returns The resolved URL, or undefined if not found\n */\nfunction resolveFromImportMap(specifier: string, importMap: ImportMap, bundleServerUrl?: string): string | undefined {\n const { imports } = importMap;\n\n if (!imports) {\n return undefined;\n }\n\n // First try exact match\n if (imports[specifier]) {\n return makeAbsoluteUrl(imports[specifier], bundleServerUrl);\n }\n\n // Then try prefix matching (for package subpaths)\n // Import maps support trailing slash patterns like \"uuid/\" -> \"/.../uuid/\"\n const matchingKeys = Object.keys(imports)\n .filter((key) => key.endsWith('/') && specifier.startsWith(key))\n .sort((a, b) => b.length - a.length); // Sort by length descending for most specific match\n\n for (const key of matchingKeys) {\n const replacement = imports[key];\n const subpath = specifier.substring(key.length);\n const resolvedUrl = replacement.endsWith('/') ? replacement + subpath : replacement;\n return makeAbsoluteUrl(resolvedUrl, bundleServerUrl);\n }\n\n return undefined;\n}\n\n/**\n * Makes a URL absolute if it's relative and a base URL is provided.\n */\nfunction makeAbsoluteUrl(url: string, baseUrl?: string): string {\n // Already absolute\n if (url.startsWith('http://') || url.startsWith('https://')) {\n return url;\n }\n\n // Make absolute using base URL if provided\n if (baseUrl) {\n // Remove trailing slash from base URL\n const cleanBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n // Ensure URL starts with /\n const cleanUrl = url.startsWith('/') ? url : `/${url}`;\n return `${cleanBase}${cleanUrl}`;\n }\n\n return url;\n}\n\n/**\n * Reads a file and rewrites bare imports to use import map URLs.\n * This is used for workers and their nested imports.\n *\n * @param filePath - The file path to read and rewrite\n * @param context - The session context with importMap and config\n * @returns The rewritten source code\n */\nexport async function rewriteImportsFromFile(\n filePath: string,\n context: PartialContext<'session', 'importMap' | 'urls' | 'config'>,\n): Promise<string> {\n const { session } = context;\n\n const source = await fsPromises.readFile(filePath, 'utf8');\n\n if (!session.importMap) {\n throw new Error('Import map is not available');\n }\n\n const bundleServerUrl = session.config.features?.relativeImportMapPaths ? undefined : session.urls.bundleServer;\n return rewriteImports(source, session.importMap, bundleServerUrl);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ms-cloudpack/bundle-server",
3
- "version": "0.8.56",
3
+ "version": "0.9.0",
4
4
  "description": "Internal bundle server for Cloudpack",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,14 +21,15 @@
21
21
  "lint": "cloudpack-scripts lint"
22
22
  },
23
23
  "dependencies": {
24
- "@ms-cloudpack/api-server": "^0.66.17",
25
- "@ms-cloudpack/common-types": "^0.33.2",
26
- "@ms-cloudpack/create-express-app": "^1.10.71",
27
- "@ms-cloudpack/import-map": "^0.12.4",
28
- "@ms-cloudpack/inline-scripts": "^0.2.78",
29
- "@ms-cloudpack/package-utilities": "^13.7.0",
24
+ "@ms-cloudpack/api-server": "^0.66.19",
25
+ "@ms-cloudpack/common-types": "^0.33.3",
26
+ "@ms-cloudpack/create-express-app": "^1.10.72",
27
+ "@ms-cloudpack/import-map": "^0.12.5",
28
+ "@ms-cloudpack/inline-scripts": "^0.2.80",
29
+ "@ms-cloudpack/package-utilities": "^13.7.1",
30
30
  "@ms-cloudpack/path-string-parsing": "^1.3.0",
31
- "@ms-cloudpack/path-utilities": "^3.2.7",
31
+ "@ms-cloudpack/path-utilities": "^3.2.8",
32
+ "es-module-lexer": "^2.0.0",
32
33
  "es-module-shims": "^2.6.1",
33
34
  "ts-dedent": "^2.2.0"
34
35
  },