11import path from 'path' ;
2-
2+ import json5 from 'json5' ;
3+ import fs from 'node:fs' ;
34import findUp from 'find-up' ;
45
56export interface PackageInfo {
@@ -8,7 +9,7 @@ export interface PackageInfo {
89 dirname : string ;
910}
1011
11- function getClosestPackageInfo ( directory : string ) {
12+ function getClosestPackageInfo ( directory : string ) : PackageInfo | undefined {
1213 const packageJsonPath = findUp . sync ( 'package.json' , {
1314 cwd : directory ,
1415 } ) ;
@@ -24,6 +25,37 @@ function getClosestPackageInfo(directory: string) {
2425 }
2526}
2627
28+ function getClosestDenoJson ( directory : string ) : PackageInfo | undefined {
29+ const denoJsonPath = findUp . sync ( 'deno.json' , {
30+ cwd : directory ,
31+ } ) ;
32+
33+ if ( denoJsonPath ) {
34+ const { name } = require ( denoJsonPath ) ;
35+
36+ return {
37+ name,
38+ path : denoJsonPath ,
39+ dirname : path . dirname ( denoJsonPath ) ,
40+ } ;
41+ }
42+
43+ // Deno also supports `deno.jsonc`
44+ const denoJsoncPath = findUp . sync ( 'deno.jsonc' , {
45+ cwd : directory ,
46+ } ) ;
47+
48+ if ( denoJsoncPath ) {
49+ const { name } = json5 . parse ( fs . readFileSync ( denoJsoncPath , 'utf-8' ) ) ;
50+
51+ return {
52+ name,
53+ path : denoJsoncPath ,
54+ dirname : path . dirname ( denoJsoncPath ) ,
55+ } ;
56+ }
57+ }
58+
2759const packageInfoCache = new Map < string , PackageInfo > ( ) ;
2860
2961export function getPackageInfo ( cwd ?: string | null ) : PackageInfo {
@@ -34,18 +66,37 @@ export function getPackageInfo(cwd?: string | null): PackageInfo {
3466 return cachedValue ;
3567 }
3668
37- let packageInfo = getClosestPackageInfo ( resolvedCwd ) ;
69+ let packageInfo : PackageInfo | undefined ;
70+
71+ // Deno projects don't necessarily have a package.json
72+ if ( typeof process . versions . deno === 'string' ) {
73+ packageInfo = getClosestDenoJson ( resolvedCwd ) ;
3874
39- while ( packageInfo && ! packageInfo . name ) {
40- packageInfo = getClosestPackageInfo (
41- path . resolve ( packageInfo . dirname , '..' ) ,
42- ) ;
75+ // No need to look further as nested deno.json files is not supported
76+ // in Deno without being a workspace member. If they are a workspace
77+ // member, they are expected to have the `name` field anyway.
4378 }
4479
45- if ( ! packageInfo || ! packageInfo . name ) {
46- throw new Error (
47- `Couldn't find parent package.json with a name field from '${ resolvedCwd } '` ,
48- ) ;
80+ if ( ! packageInfo ) {
81+ packageInfo = getClosestPackageInfo ( resolvedCwd ) ;
82+
83+ while ( packageInfo && ! packageInfo . name ) {
84+ packageInfo = getClosestPackageInfo (
85+ path . resolve ( packageInfo . dirname , '..' ) ,
86+ ) ;
87+ }
88+
89+ if ( ! packageInfo || ! packageInfo . name ) {
90+ if ( typeof process . versions . deno === 'string' ) {
91+ throw new Error (
92+ `Couldn't find parent deno.json, deno.jsonc or package.json with a name field from '${ resolvedCwd } '` ,
93+ ) ;
94+ } else {
95+ throw new Error (
96+ `Couldn't find parent package.json with a name field from '${ resolvedCwd } '` ,
97+ ) ;
98+ }
99+ }
49100 }
50101
51102 packageInfoCache . set ( resolvedCwd , packageInfo ) ;
0 commit comments