1
+ const CONFIG_FILE = "./config.json" ;
2
+
3
+ async function readConfig ( ) : Promise < string > {
4
+ try {
5
+ return await Deno . readTextFile ( CONFIG_FILE ) ;
6
+ } catch ( error ) {
7
+ if ( error instanceof Deno . errors . NotFound ) {
8
+ // Return sample config if config.json doesn't exist
9
+ return await Deno . readTextFile ( "./config.json.sample" ) ;
10
+ }
11
+ throw error ;
12
+ }
13
+ }
14
+
15
+ async function writeConfig ( configData : string ) : Promise < void > {
16
+ await Deno . writeTextFile ( CONFIG_FILE , configData ) ;
17
+ }
18
+
19
+ async function rebootSystem ( ) : Promise < void > {
20
+ try {
21
+ // In test mode, don't actually reboot
22
+ if ( Deno . env . get ( "PIOSK_TEST_MODE" ) === "true" ) {
23
+ console . log ( "Test mode: Would reboot system" ) ;
24
+ return ;
25
+ }
26
+
27
+ const command = new Deno . Command ( "reboot" , {
28
+ stdout : "piped" ,
29
+ stderr : "piped"
30
+ } ) ;
31
+ await command . output ( ) ;
32
+ } catch ( error ) {
33
+ console . error ( "Reboot command failed:" , error ) ;
34
+ throw error ;
35
+ }
36
+ }
37
+
38
+ async function serveStaticFile ( pathname : string ) : Promise < Response > {
39
+ let filePath : string ;
40
+
41
+ if ( pathname === "/" || pathname === "/index.html" ) {
42
+ filePath = "./web/index.html" ;
43
+ } else {
44
+ // Remove leading slash and serve from web directory
45
+ filePath = `./web${ pathname } ` ;
46
+ }
47
+
48
+ try {
49
+ const file = await Deno . readFile ( filePath ) ;
50
+
51
+ // Determine content type
52
+ let contentType = "text/plain" ;
53
+ if ( filePath . endsWith ( ".html" ) ) {
54
+ contentType = "text/html" ;
55
+ } else if ( filePath . endsWith ( ".js" ) ) {
56
+ contentType = "application/javascript" ;
57
+ } else if ( filePath . endsWith ( ".css" ) ) {
58
+ contentType = "text/css" ;
59
+ } else if ( filePath . endsWith ( ".json" ) ) {
60
+ contentType = "application/json" ;
61
+ }
62
+
63
+ return new Response ( file , {
64
+ headers : { "Content-Type" : contentType } ,
65
+ } ) ;
66
+ } catch ( error ) {
67
+ if ( error instanceof Deno . errors . NotFound ) {
68
+ return new Response ( "Not Found" , { status : 404 } ) ;
69
+ }
70
+ console . error ( "Error serving file:" , error ) ;
71
+ return new Response ( "Internal Server Error" , { status : 500 } ) ;
72
+ }
73
+ }
74
+
75
+ async function handler ( req : Request ) : Promise < Response > {
76
+ const url = new URL ( req . url ) ;
77
+
78
+ // Handle API endpoints
79
+ if ( url . pathname === "/config" ) {
80
+ if ( req . method === "GET" ) {
81
+ try {
82
+ const config = await readConfig ( ) ;
83
+ return new Response ( config , {
84
+ headers : { "Content-Type" : "application/json" } ,
85
+ } ) ;
86
+ } catch ( error ) {
87
+ console . error ( "Error reading config:" , error ) ;
88
+ return new Response ( "Could not read config." , { status : 500 } ) ;
89
+ }
90
+ }
91
+
92
+ if ( req . method === "POST" ) {
93
+ try {
94
+ const configData = await req . text ( ) ;
95
+
96
+ // Validate JSON
97
+ JSON . parse ( configData ) ;
98
+
99
+ await writeConfig ( JSON . stringify ( JSON . parse ( configData ) , null , " " ) ) ;
100
+
101
+ // Reboot system
102
+ try {
103
+ await rebootSystem ( ) ;
104
+ return new Response ( "New config applied; rebooting for changes to take effect..." , { status : 200 } ) ;
105
+ } catch ( rebootError ) {
106
+ console . error ( "Reboot error:" , rebootError ) ;
107
+ return new Response ( "Could not reboot to apply config. Retry or reboot manually." , { status : 500 } ) ;
108
+ }
109
+ } catch ( error ) {
110
+ console . error ( "Error saving config:" , error ) ;
111
+ return new Response ( "Could not save config." , { status : 500 } ) ;
112
+ }
113
+ }
114
+ }
115
+
116
+ // Handle static files
117
+ return await serveStaticFile ( url . pathname ) ;
118
+ }
119
+
120
+ const port = parseInt ( Deno . env . get ( "PORT" ) || "80" ) ;
121
+ console . log ( `PiOSK Deno server starting on port ${ port } ...` ) ;
122
+
123
+ Deno . serve ( { port } , handler ) ;
0 commit comments