Skip to content

Commit a5864a4

Browse files
simple file server
1 parent de51cad commit a5864a4

5 files changed

Lines changed: 206 additions & 0 deletions

File tree

main.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
:root {
2+
color-scheme: light dark;
3+
}
4+
5+
:root {
6+
--bg: white;
7+
--text: black;
8+
}
9+
10+
@media (prefers-color-scheme: dark) {
11+
:root {
12+
--bg: black;
13+
--text: white;
14+
}
15+
}
16+
17+
body {
18+
background-color: var(--bg);
19+
color: var(--text);
20+
}
21+
22+
a {
23+
color: green;
24+
}

package-lock.json

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "file-server-example",
3+
"version": "0.0.0",
4+
"description": "File Server Example",
5+
"homepage": "https://github.com/functionalscript/file-server-example#readme",
6+
"bugs": {
7+
"url": "https://github.com/functionalscript/file-server-example/issues"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/functionalscript/file-server-example.git"
12+
},
13+
"license": "MIT",
14+
"author": "Sergey Shandar",
15+
"type": "module",
16+
"main": "server.f.ts",
17+
"scripts": {
18+
"test": "fjs t",
19+
"server": "fjs r ./server.f.ts"
20+
},
21+
"dependencies": {
22+
"functionalscript": "^0.11.6"
23+
},
24+
"devDependencies": {
25+
"typescript": "^5.9.3"
26+
}
27+
}

server.f.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { utf8 } from 'functionalscript/text/module.f.js'
2+
import { type Vec } from 'functionalscript/types/bit_vec/module.f.js'
3+
import { pure } from 'functionalscript/types/effects/module.f.js'
4+
import {
5+
createServer,
6+
listen,
7+
forever,
8+
type NodeProgram,
9+
type IncomingMessage,
10+
readFile,
11+
type ServerResponse,
12+
log,
13+
readdir,
14+
type IoResult,
15+
type Dirent,
16+
} from 'functionalscript/types/effects/node/module.f.js'
17+
import { htmlToString } from 'functionalscript/html/module.f.js'
18+
import { concat } from 'functionalscript/path/module.f.js'
19+
20+
const listener = ({ url }: IncomingMessage) => {
21+
const path = url.split('?')[0] ?? ''
22+
const file = '.' + path
23+
24+
const dirLink = ({ name, isFile }: Dirent) => {
25+
const href = '/' + concat(path)(name)
26+
return [['a', { href }, name + (isFile ? '' : '/')], '\n'] as const
27+
}
28+
29+
const dirPage = (v: readonly Dirent[]) => htmlToString(
30+
['html',
31+
['head',
32+
['link', { rel: 'stylesheet', href: '/main.css' }]
33+
],
34+
['body',
35+
['pre',
36+
...v.flatMap(dirLink)
37+
]
38+
]
39+
])
40+
41+
const orReadDir = (r: IoResult<Vec>) => r[0] === 'ok'
42+
? pure(r)
43+
: readdir(file, {})
44+
.step(([s, v]) => pure([s, utf8(s === 'ok' ? dirPage(v) : '')] as const))
45+
46+
return log(`reading ${file}`)
47+
.step(() => readFile(file))
48+
.step(orReadDir)
49+
.step(([s, v]) => {
50+
const o = s === 'ok'
51+
return pure({
52+
status: o ? 200 : 404,
53+
headers: {},
54+
body: o ? v : utf8('404 not found'),
55+
})
56+
})
57+
}
58+
59+
const main: NodeProgram = () => createServer(listener)
60+
.step(server => listen(server, 3000))
61+
.step(forever)
62+
63+
export default main

tsconfig.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
// Visit https://aka.ms/tsconfig to read more about this file
3+
"compilerOptions": {
4+
// File Layout
5+
// "rootDir": "./src",
6+
// "outDir": "./dist",
7+
8+
// Environment Settings
9+
// See also https://aka.ms/tsconfig/module
10+
"module": "nodenext",
11+
"target": "esnext",
12+
"types": [],
13+
// For nodejs:
14+
// "lib": ["esnext"],
15+
// "types": ["node"],
16+
// and npm install -D @types/node
17+
18+
// Other Outputs
19+
"sourceMap": true,
20+
"declaration": true,
21+
"declarationMap": true,
22+
23+
// Stricter Typechecking Options
24+
"noUncheckedIndexedAccess": true,
25+
"exactOptionalPropertyTypes": true,
26+
27+
// Style Options
28+
// "noImplicitReturns": true,
29+
// "noImplicitOverride": true,
30+
// "noUnusedLocals": true,
31+
// "noUnusedParameters": true,
32+
// "noFallthroughCasesInSwitch": true,
33+
// "noPropertyAccessFromIndexSignature": true,
34+
35+
// Recommended Options
36+
"strict": true,
37+
"jsx": "react-jsx",
38+
"verbatimModuleSyntax": true,
39+
"isolatedModules": true,
40+
"noUncheckedSideEffectImports": true,
41+
"moduleDetection": "force",
42+
"skipLibCheck": true,
43+
44+
//
45+
"noEmit": true
46+
}
47+
}

0 commit comments

Comments
 (0)