@@ -2,7 +2,7 @@ import "./constants";
22import {
33 Lockfile ,
44 PackageData ,
5- InternalPackageData ,
5+ LockfilePackage ,
66 PackageLoadMetadata ,
77 PackageManagerAPI ,
88 PackageManagerModule ,
@@ -23,6 +23,7 @@ import {
2323 resolvePath ,
2424 initNodeModules ,
2525 ensureDirNode ,
26+ isAbsolute ,
2627} from "./compat" ;
2728import { Installer } from "./installer" ;
2829import { createContextWrapper } from "./common/contextManager" ;
@@ -35,10 +36,12 @@ import { createContextWrapper } from "./common/contextManager";
3536 * @private
3637 */
3738export async function initializePackageIndex (
38- lockFilePromise : Promise < Lockfile > ,
39+ lockFilePromise : Promise < Lockfile | string > ,
3940) {
4041 await initNodeModules ( ) ;
41- const lockfile = await lockFilePromise ;
42+ const lockfile_ = await lockFilePromise ;
43+ const lockfile : Lockfile =
44+ typeof lockfile_ === "string" ? JSON . parse ( lockfile_ ) : lockfile_ ;
4245 if ( ! lockfile . packages ) {
4346 throw new Error (
4447 "Loaded pyodide lock file does not contain the expected key 'packages'." ,
@@ -123,7 +126,7 @@ export class PackageManager {
123126
124127 private _lock = createLock ( ) ;
125128
126- public installBaseUrl : string ;
129+ public installBaseUrl ? : string ;
127130
128131 /**
129132 * The function to use for stdout and stderr, defaults to console.log and console.error
@@ -147,11 +150,15 @@ export class PackageManager {
147150 this . #module = pyodideModule ;
148151 this . #installer = new Installer ( api , pyodideModule ) ;
149152
150- const lockfileBase = calculateInstallBaseUrl ( this . #api. config . lockFileURL ) ;
151153 if ( IN_NODE ) {
152- this . installBaseUrl = this . #api. config . packageCacheDir ?? lockfileBase ;
154+ // In node, we'll try first to load from the packageCacheDir and then fall
155+ // back to cdnURL
156+ this . installBaseUrl =
157+ this . #api. config . packageCacheDir ?? API . config . packageBaseUrl ;
158+ this . cdnURL = this . #api. config . cdnUrl ;
153159 } else {
154- this . installBaseUrl = lockfileBase ;
160+ // use packageBaseUrl as the base URL for the packages
161+ this . installBaseUrl = this . #api. config . packageBaseUrl ;
155162 }
156163
157164 this . stdout = ( msg : string ) => {
@@ -248,7 +255,7 @@ export class PackageManager {
248255 checkIntegrity : true ,
249256 } ,
250257 ) : Promise < Array < PackageData > > {
251- const loadedPackageData = new Set < InternalPackageData > ( ) ;
258+ const loadedPackageData = new Set < LockfilePackage > ( ) ;
252259 const pkgNames = toStringArray ( names ) ;
253260
254261 const toLoad = this . recursiveDependencies ( pkgNames ) ;
@@ -450,6 +457,13 @@ export class PackageManager {
450457 }
451458 const lockfilePackage = this . #api. lockfile_packages [ pkg . normalizedName ] ;
452459 fileName = lockfilePackage . file_name ;
460+ // TODO: Node caching logic assumes relative here...
461+ if ( ! isAbsolute ( fileName ) && ! this . installBaseUrl ) {
462+ throw new Error (
463+ `Lock file file_name for package "${ pkg . name } " is relative path "${ fileName } " but no packageBaseUrl provided to loadPyodide.` ,
464+ ) ;
465+ }
466+
453467 uri = resolvePath ( fileName , this . installBaseUrl ) ;
454468 fileSubResourceHash = "sha256-" + base16ToBase64 ( lockfilePackage . sha256 ) ;
455469 } else {
@@ -464,7 +478,12 @@ export class PackageManager {
464478 DEBUG && console . debug ( `Downloading package ${ pkg . name } from ${ uri } ` ) ;
465479 return await loadBinaryFile ( uri , fileSubResourceHash ) ;
466480 } catch ( e ) {
467- if ( ! IN_NODE || pkg . channel !== this . defaultChannel ) {
481+ if (
482+ ! IN_NODE ||
483+ pkg . channel !== this . defaultChannel ||
484+ ! fileName ||
485+ fileName . startsWith ( "/" )
486+ ) {
468487 throw e ;
469488 }
470489 }
@@ -538,7 +557,7 @@ export class PackageManager {
538557 private async downloadAndInstall (
539558 pkg : PackageLoadMetadata ,
540559 toLoad : Map < string , PackageLoadMetadata > ,
541- loaded : Set < InternalPackageData > ,
560+ loaded : Set < LockfilePackage > ,
542561 failed : Map < string , Error > ,
543562 checkIntegrity : boolean = true ,
544563 ) {
@@ -572,10 +591,6 @@ export class PackageManager {
572591 }
573592 }
574593
575- public setCdnUrl ( url : string ) {
576- this . cdnURL = url ;
577- }
578-
579594 /**
580595 * Flushes the stdout and stderr buffers, that were collected before the
581596 * stdout and stderr functions were set.
@@ -641,7 +656,7 @@ function filterPackageData({
641656 version,
642657 file_name,
643658 package_type,
644- } : InternalPackageData ) : PackageData {
659+ } : LockfilePackage ) : PackageData {
645660 return { name, version, fileName : file_name , packageType : package_type } ;
646661}
647662
@@ -666,25 +681,6 @@ export function toStringArray(str: string | PyProxy | string[]): string[] {
666681 return str ;
667682}
668683
669- /**
670- * Calculates the install base url for the package manager.
671- * exported for testing
672- * @param lockFileURL
673- * @returns the install base url
674- * @private
675- */
676- export function calculateInstallBaseUrl ( lockFileURL : string ) {
677- // 1. If the lockfile URL includes a path with slash (file url in Node.js or http url in browser), use the directory of the lockfile URL
678- // 2. Otherwise, fallback to the current location
679- // 2.1. In the browser, use `location` to get the current location
680- // 2.2. In Node.js just use the pwd
681- return (
682- lockFileURL . substring ( 0 , lockFileURL . lastIndexOf ( "/" ) + 1 ) ||
683- globalThis . location ?. toString ( ) ||
684- "."
685- ) ;
686- }
687-
688684export let loadPackage : typeof PackageManager . prototype . loadPackage ;
689685/**
690686 * An object whose keys are the names of the loaded packages and whose values
@@ -710,13 +706,6 @@ if (typeof API !== "undefined" && typeof Module !== "undefined") {
710706 */
711707 loadedPackages = singletonPackageManager . loadedPackages ;
712708
713- // TODO: Find a better way to register these functions
714- API . setCdnUrl = singletonPackageManager . setCdnUrl . bind (
715- singletonPackageManager ,
716- ) ;
717-
718- API . lockfileBaseUrl = singletonPackageManager . installBaseUrl ;
719-
720709 API . flushPackageManagerBuffers = singletonPackageManager . flushBuffers . bind (
721710 singletonPackageManager ,
722711 ) ;
0 commit comments