1+ import { isDeno } from "@commontools/utils/env" ;
12import { ProgramResolver , Source } from "./interface.ts" ;
3+ import { dirname , join } from "@std/path" ;
24
35export class InMemoryProgram implements ProgramResolver {
46 private modules : Record < string , string > ;
@@ -8,12 +10,12 @@ export class InMemoryProgram implements ProgramResolver {
810 this . _main = main ;
911 }
1012
11- main ( ) : Source {
13+ main ( ) : Promise < Source > {
1214 const main = this . modules [ this . _main ] ;
1315 if ( ! main ) {
1416 throw new Error ( `${ this . _main } not in modules.` ) ;
1517 }
16- return { name : this . _main , contents : main } ;
18+ return Promise . resolve ( { name : this . _main , contents : main } ) ;
1719 }
1820
1921 resolveSource ( identifier : string ) : Promise < Source | undefined > {
@@ -22,3 +24,83 @@ export class InMemoryProgram implements ProgramResolver {
2224 return Promise . resolve ( { contents, name : identifier } ) ;
2325 }
2426}
27+
28+ // Resolve a program using the file system.
29+ // Deno-only.
30+ export class FileSystemProgramResolver implements ProgramResolver {
31+ private fsRoot : string ;
32+ private _main : Source ;
33+ constructor ( mainPath : string ) {
34+ this . fsRoot = dirname ( mainPath ) ;
35+ this . _main = {
36+ name : mainPath . substring ( this . fsRoot . length ) ,
37+ contents : this . #readFile( mainPath ) ,
38+ } ;
39+ }
40+
41+ main ( ) : Promise < Source > {
42+ return Promise . resolve ( this . _main ) ;
43+ }
44+
45+ resolveSource ( specifier : string ) : Promise < Source | undefined > {
46+ if ( ! specifier || specifier [ 0 ] !== "/" ) {
47+ return Promise . resolve ( undefined ) ;
48+ }
49+ const absPath = join (
50+ this . fsRoot ,
51+ specifier . substring ( 1 , specifier . length ) ,
52+ ) ;
53+ return Promise . resolve ( {
54+ name : specifier ,
55+ contents : this . #readFile( absPath ) ,
56+ } ) ;
57+ }
58+
59+ #readFile( path : string ) : string {
60+ if ( ! isDeno ( ) ) {
61+ throw new Error (
62+ "FileSystemProgramResolver is not supported in this environment." ,
63+ ) ;
64+ }
65+ return Deno . readTextFileSync ( path ) ;
66+ }
67+ }
68+
69+ // Resolve a program from HTTP.
70+ export class HttpProgramResolver implements ProgramResolver {
71+ #httpRoot: string ;
72+ #mainUrl: URL ;
73+ #main?: Promise < Source > ;
74+ constructor ( main : string | URL ) {
75+ this . #mainUrl = ! ( main instanceof URL ) ? new URL ( main ) : main ;
76+ this . #httpRoot = dirname ( this . #mainUrl. pathname ) ;
77+ }
78+
79+ main ( ) : Promise < Source > {
80+ if ( ! this . #main) {
81+ this . #main = this . #fetch( this . #mainUrl) ;
82+ }
83+ return this . #main;
84+ }
85+
86+ resolveSource ( specifier : string ) : Promise < Source | undefined > {
87+ if ( ! specifier || specifier [ 0 ] !== "/" ) {
88+ return Promise . resolve ( undefined ) ;
89+ }
90+ const url = new URL ( this . #mainUrl) ;
91+ url . pathname = join (
92+ this . #httpRoot,
93+ specifier . substring ( 1 , specifier . length ) ,
94+ ) ;
95+ return this . #fetch( url ) ;
96+ }
97+
98+ async #fetch( url : URL ) : Promise < Source > {
99+ const res = await fetch ( url ) ;
100+ const contents = await res . text ( ) ;
101+ return {
102+ name : url . pathname . substring ( this . #httpRoot. length ) ,
103+ contents,
104+ } ;
105+ }
106+ }
0 commit comments