@@ -116,12 +116,16 @@ export async function jsrPkgToFlatpakData(pkg: Pkg): Promise<FlatpakData[]> {
116116 const [ checksumType , checksumValue ] = splitOnce ( fileMeta . checksum , "-" ) ;
117117
118118 const url = `https://jsr.io/${ pkg . module } /${ pkg . version } ${ fileUrl } ` ;
119- let [ fileDir , fileName ] = splitOnce ( fileUrl , "/" , "right" ) ;
120- const dest = `vendor/jsr.io/${ pkg . module } /${ pkg . version } ${ fileDir } ` ;
121-
122- if ( shouldHash ( fileName ) ) {
123- fileName = await shortHash ( fileName ) ;
124- }
119+ const segments = fileUrl . split ( "/" ) . filter ( Boolean ) ;
120+ const hashedSegments = await Promise . all (
121+ segments . map ( async ( part ) =>
122+ shouldHash ( part ) ? await shortHash ( part ) : part
123+ ) ,
124+ ) ;
125+ const fileName = hashedSegments . pop ( ) ;
126+ const dest = `vendor/jsr.io/${ pkg . module } /${ pkg . version } ${
127+ hashedSegments . length > 0 ? "/" + hashedSegments . join ( "/" ) : ""
128+ } `;
125129
126130 flatpkData . push ( {
127131 type : "file" ,
@@ -143,8 +147,17 @@ export async function jsrPkgToFlatpakData(pkg: Pkg): Promise<FlatpakData[]> {
143147 "-" ,
144148 ) ;
145149 const url = `https://jsr.io/${ pkg . module } /${ pkg . version } ${ fileUrl } ` ;
146- const [ fileDir , fileName ] = splitOnce ( fileUrl , "/" , "right" ) ;
147- const dest = `vendor/jsr.io/${ pkg . module } /${ pkg . version } ${ fileDir } ` ;
150+ const segments = fileUrl . split ( "/" ) . filter ( Boolean ) ;
151+ const hashedSegments = await Promise . all (
152+ segments . map ( async ( part ) =>
153+ shouldHash ( part ) ? await shortHash ( part ) : part
154+ ) ,
155+ ) ;
156+ const fileName = hashedSegments . pop ( ) ;
157+ const dest = `vendor/jsr.io/${ pkg . module } /${ pkg . version } ${
158+ hashedSegments . length > 0 ? "/" + hashedSegments . join ( "/" ) : ""
159+ } `;
160+
148161 flatpkData . push ( {
149162 type : "file" ,
150163 url,
@@ -158,6 +171,106 @@ export async function jsrPkgToFlatpakData(pkg: Pkg): Promise<FlatpakData[]> {
158171 return flatpkData ;
159172}
160173
174+ /**
175+ * Checks if a package is a JSR package accessed via npm.jsr.io
176+ * @param module The module identifier (e.g., "@jsr/sigma__deno-compat")
177+ * @returns true if this is a JSR package via npm compatibility layer
178+ */
179+ function isJsrNpmPackage ( module : string ) : boolean {
180+ return module . startsWith ( "@jsr/" ) ;
181+ }
182+
183+ /**
184+ * Converts JSR package (accessed via npm.jsr.io) into FlatpakData objects.
185+ * JSR packages via npm have tarball URLs and integrity in the lock file,
186+ * so we don't need to fetch from a registry.
187+ * @param pkg The JSR-via-npm package information.
188+ * @param lockData The lock file data for this specific package.
189+ * @returns A promise that resolves to an array of FlatpakData objects.
190+ */
191+ export function jsrNpmPkgToFlatpakData (
192+ pkg : Pkg ,
193+ // deno-lint-ignore no-explicit-any
194+ lockData : any ,
195+ ) : FlatpakData [ ] {
196+ const tarballUrl = lockData . tarball ;
197+ const integrity = lockData . integrity ;
198+
199+ if ( ! tarballUrl || ! integrity ) {
200+ throw new Error (
201+ `Missing tarball or integrity for JSR package ${ pkg . module } @${ pkg . version } ` ,
202+ ) ;
203+ }
204+
205+ const [ checksumType , checksumValue ] = splitOnce ( integrity , "-" ) ;
206+
207+ const registryContents = JSON . stringify ( {
208+ name : pkg . module ,
209+ "dist-tags" : { } ,
210+ versions : {
211+ [ pkg . version ] : {
212+ dist : {
213+ integrity : integrity ,
214+ tarball : tarballUrl ,
215+ } ,
216+ } ,
217+ } ,
218+ } ) ;
219+
220+ // Deno's npm cache resolution for JSR packages can be inconsistent
221+ // Sometimes it looks under npm.jsr.io, sometimes under registry.npmjs.org
222+ // We generate entries for both paths to ensure compatibility
223+ const results : FlatpakData [ ] = [ ] ;
224+
225+ // Create inline registry.json for npm.jsr.io path
226+ results . push ( {
227+ type : "inline" ,
228+ contents : registryContents ,
229+ dest : `deno_dir/npm/npm.jsr.io/${ pkg . module } ` ,
230+ "dest-filename" : "registry.json" ,
231+ } ) ;
232+
233+ // Create inline registry.json for registry.npmjs.org path
234+ results . push ( {
235+ type : "inline" ,
236+ contents : registryContents ,
237+ dest : `deno_dir/npm/registry.npmjs.org/${ pkg . module } ` ,
238+ "dest-filename" : "registry.json" ,
239+ } ) ;
240+
241+ // Archive for npm.jsr.io path
242+ const pkgDataJsr : FlatpakData = {
243+ type : "archive" ,
244+ "archive-type" : "tar-gzip" ,
245+ url : tarballUrl ,
246+ [ checksumType ] : base64ToHex ( checksumValue ) ,
247+ dest : `deno_dir/npm/npm.jsr.io/${ pkg . module } /${ pkg . version } ` ,
248+ } ;
249+
250+ if ( pkg . cpu ) {
251+ pkgDataJsr [ "only-arches" ] = [ pkg . cpu ] ;
252+ }
253+
254+ results . push ( pkgDataJsr ) ;
255+
256+ // Archive for registry.npmjs.org path
257+ const pkgDataNpm : FlatpakData = {
258+ type : "archive" ,
259+ "archive-type" : "tar-gzip" ,
260+ url : tarballUrl ,
261+ [ checksumType ] : base64ToHex ( checksumValue ) ,
262+ dest : `deno_dir/npm/registry.npmjs.org/${ pkg . module } /${ pkg . version } ` ,
263+ } ;
264+
265+ if ( pkg . cpu ) {
266+ pkgDataNpm [ "only-arches" ] = [ pkg . cpu ] ;
267+ }
268+
269+ results . push ( pkgDataNpm ) ;
270+
271+ return results ;
272+ }
273+
161274/**
162275 * Converts NPM package information into an array of FlatpakData objects.
163276 * It fetches metadata for the package and creates entries for the package's
@@ -229,25 +342,60 @@ export async function main(
229342 return { module : r [ 0 ] , version : r [ 1 ] , name } ;
230343 } ) ;
231344 jsrPkgs ;
232- const npmPkgs : Pkg [ ] = ! lock . npm ? [ ] : Object . entries ( lock . npm )
233- . filter ( (
234- // deno-lint-ignore no-explicit-any
235- [ _key , val ] : any ,
236- ) => ( val . os === undefined || val . os ?. at ( 0 ) === "linux" ) )
345+
346+ // Process npm packages, separating JSR packages from regular npm packages
347+ // deno-lint-ignore no-explicit-any
348+ const npmEntries : Array < [ string , any ] > = ! lock . npm
349+ ? [ ]
350+ : Object . entries ( lock . npm )
351+ . filter ( (
352+ // deno-lint-ignore no-explicit-any
353+ [ _key , val ] : any ,
354+ ) => ( val . os === undefined || val . os ?. at ( 0 ) === "linux" ) ) ;
355+
356+ // deno-lint-ignore no-explicit-any
357+ const npmPkgs : Array < [ Pkg , any ] > = npmEntries
358+ . filter ( ( [ key , _val ] ) => {
359+ const r = key . match ( / ( ^ @ ? .+ ?) @ ( [ ^ _ ] + ?) (? = _ | $ ) / ) ! ;
360+ return ! isJsrNpmPackage ( r [ 1 ] ) ;
361+ } )
237362 // deno-lint-ignore no-explicit-any
238363 . map ( ( [ key , val ] : [ string , any ] ) => {
239364 const r = key . match ( / ( ^ @ ? .+ ?) @ ( [ ^ _ ] + ?) (? = _ | $ ) / ) ! ;
240365 const name = r [ 1 ] . includes ( "/" ) ? r [ 1 ] . split ( "/" ) [ 1 ] : r [ 1 ] ;
241366 const cpu = val . cpu ?. at ( 0 ) ;
242- return {
243- module : r [ 1 ] ,
244- version : r [ 2 ] ,
245- name,
246- cpu : cpu === "x64" ? "x86_64" : cpu === "arm64" ? "aarch64" : cpu ,
247- } ;
367+ return [
368+ {
369+ module : r [ 1 ] ,
370+ version : r [ 2 ] ,
371+ name,
372+ cpu : cpu === "x64" ? "x86_64" : cpu === "arm64" ? "aarch64" : cpu ,
373+ } ,
374+ val ,
375+ ] ;
376+ } ) ;
377+
378+ // deno-lint-ignore no-explicit-any
379+ const jsrNpmPkgs : Array < [ Pkg , any ] > = npmEntries
380+ . filter ( ( [ key , _val ] ) => {
381+ const r = key . match ( / ( ^ @ ? .+ ?) @ ( [ ^ _ ] + ?) (? = _ | $ ) / ) ! ;
382+ return isJsrNpmPackage ( r [ 1 ] ) ;
383+ } )
384+ // deno-lint-ignore no-explicit-any
385+ . map ( ( [ key , val ] : [ string , any ] ) => {
386+ const r = key . match ( / ( ^ @ ? .+ ?) @ ( [ ^ _ ] + ?) (? = _ | $ ) / ) ! ;
387+ const name = r [ 1 ] . includes ( "/" ) ? r [ 1 ] . split ( "/" ) [ 1 ] : r [ 1 ] ;
388+ const cpu = val . cpu ?. at ( 0 ) ;
389+ return [
390+ {
391+ module : r [ 1 ] ,
392+ version : r [ 2 ] ,
393+ name,
394+ cpu : cpu === "x64" ? "x86_64" : cpu === "arm64" ? "aarch64" : cpu ,
395+ } ,
396+ val ,
397+ ] ;
248398 } ) ;
249- //url: https://registry.npmjs.org/@napi -rs/cli/-/cli-2.18.4.tgz
250- npmPkgs ;
251399 const httpPkgsData = ! lock . remote
252400 ? [ ]
253401 : Object . entries ( lock . remote ) . map ( async ( [ urlStr , checksum ] ) => {
@@ -270,9 +418,14 @@ export async function main(
270418 await Promise . all (
271419 jsrPkgs . map ( ( pkg ) => jsrPkgToFlatpakData ( pkg ) ) ,
272420 ) . then ( ( r ) => r . flat ( ) ) ,
273- await Promise . all ( npmPkgs . map ( ( pkg ) => npmPkgToFlatpakData ( pkg ) ) ) . then (
274- ( r ) => r . flat ( ) ,
275- ) ,
421+ await Promise . all (
422+ npmPkgs . map ( ( [ pkg , _lockData ] ) => npmPkgToFlatpakData ( pkg ) ) ,
423+ ) . then ( ( r ) => r . flat ( ) ) ,
424+ await Promise . all (
425+ jsrNpmPkgs . map ( ( [ pkg , lockData ] ) =>
426+ jsrNpmPkgToFlatpakData ( pkg , lockData )
427+ ) ,
428+ ) . then ( ( r ) => r . flat ( ) ) ,
276429 await Promise . all ( httpPkgsData ) ,
277430 ] . flat ( ) ;
278431 // console.log(flatpakData);
0 commit comments