Skip to content

Commit c26beca

Browse files
WIP
1 parent d225d78 commit c26beca

17 files changed

+766
-87
lines changed

build/mirrorUnpkg.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ Promise.all(
1010
files.map(f =>
1111
fetch('https://unpkg.com/[email protected]/' + f)
1212
.then(res => res.text())
13-
.then(text => writeFile('www_root/api/' + f, text))
13+
.then(text => writeFile('www_root/openapi/' + f, text))
1414
)
1515
)

build/openAPIDoc.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const swaggerDefinition = {
2929
url: '{URL}',
3030
variables: {
3131
URL: {
32-
default: 'http://localhost:3030'
32+
default: 'http://localhost:3030/API'
3333
}
3434
}
3535
}
@@ -284,7 +284,7 @@ const swaggerDefinition = {
284284
}
285285

286286
writeFileSync(
287-
'www_root/api/openapi-norch-' + version + '.json',
287+
'www_root/openapi/openapi-norch-' + version + '.json',
288288
JSON.stringify(
289289
swaggerJsdoc({
290290
swaggerDefinition,

src/API.js

+43-26
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
export class API {
2-
constructor (index, sendResponse, events) {
3-
this.index = index
4-
this.sendResponse = sendResponse
2+
constructor(index, sendResponse, events, logResponse) {
53
this.events = events
4+
this.index = index
5+
this.logResponse = logResponse
66
this.ready = false
7+
this.sendResponse = sendResponse
78
events.on('ready', () => (this.ready = true))
89
}
910

@@ -19,10 +20,20 @@ export class API {
1920

2021
param = (req, name) => this.params(req, name)[0]
2122

22-
sendJSONResponse = (body, res) => {
23+
sendJSONResponse = (body, req, res, statusCode) => {
2324
res.setHeader('Content-Type', 'application/json; charset=utf-8')
24-
res.writeHead(200)
25+
res.writeHead(statusCode)
2526
res.end(JSON.stringify(body, null, 2))
27+
this.logResponse(statusCode, req.url)
28+
}
29+
30+
internalServerError = (e, req, res) => {
31+
this.sendJSONResponse(
32+
{ status: 500, error: 'Internal Server Error' },
33+
req,
34+
res,
35+
500
36+
)
2637
}
2738

2839
/**
@@ -40,7 +51,7 @@ export class API {
4051
ALL_DOCUMENTS = (req, res) =>
4152
this.index
4253
.ALL_DOCUMENTS(+this.params(req, 'LIMIT') || undefined)
43-
.then(ad => this.sendJSONResponse(ad, res))
54+
.then(ad => this.sendJSONResponse(ad, req, res, 200))
4455

4556
/**
4657
* @openapi
@@ -57,7 +68,7 @@ export class API {
5768
BUCKETS = (req, res) =>
5869
this.index
5970
.BUCKETS(...this.params(req, 'TOKENSPACE'))
60-
.then(b => this.sendJSONResponse(b, res))
71+
.then(b => this.sendJSONResponse(b, req, res, 200))
6172

6273
/**
6374
* @openapi
@@ -74,7 +85,7 @@ export class API {
7485
DELETE = (req, res) =>
7586
this.index
7687
.DELETE(...this.params(req, 'ID'))
77-
.then(idxRes => this.sendJSONResponse(idxRes, res))
88+
.then(idxRes => this.sendJSONResponse(idxRes, req, res, 200))
7889

7990
// TODO: DELETE_RAW?
8091

@@ -98,7 +109,7 @@ export class API {
98109
this.index
99110
.DICTIONARY(...this.params(req, 'TOKENSPACE'))
100111
.then(d => d.slice(0, +this.params(req, 'LIMIT')))
101-
.then(d => this.sendJSONResponse(d, res))
112+
.then(d => this.sendJSONResponse(d, req, res, 200))
102113

103114
/**
104115
* @openapi
@@ -120,7 +131,7 @@ export class API {
120131
this.index
121132
.DISTINCT(...this.params(req, 'TOKENSPACE'))
122133
.then(d => d.slice(0, +this.params(req, 'LIMIT')))
123-
.then(d => this.sendJSONResponse(d, res))
134+
.then(d => this.sendJSONResponse(d, req, res, 200))
124135

125136
/**
126137
* @openapi
@@ -137,7 +148,7 @@ export class API {
137148
DOCUMENTS = (req, res) =>
138149
this.index
139150
.DOCUMENTS(...this.params(req, 'ID'))
140-
.then(b => this.sendJSONResponse(b, res))
151+
.then(b => this.sendJSONResponse(b, req, res, 200))
141152

142153
// TODO: DOCUMENT_VECTORS?
143154

@@ -153,7 +164,7 @@ export class API {
153164
* description: A dump of the index
154165
*/
155166
EXPORT = (req, res) =>
156-
this.index.EXPORT().then(exp => this.sendJSONResponse(exp, res))
167+
this.index.EXPORT().then(exp => this.sendJSONResponse(exp, req, res, 200))
157168

158169
/**
159170
* @openapi
@@ -173,7 +184,7 @@ export class API {
173184
FACETS = (req, res) =>
174185
this.index
175186
.FACETS(...this.params(req, 'TOKENSPACE'))
176-
.then(b => this.sendJSONResponse(b, res))
187+
.then(b => this.sendJSONResponse(b, req, res, 200))
177188

178189
/**
179190
* @openapi
@@ -186,7 +197,7 @@ export class API {
186197
* description: An array of field names
187198
*/
188199
FIELDS = (req, res) =>
189-
this.index.FIELDS().then(f => this.sendJSONResponse(f, res))
200+
this.index.FIELDS().then(f => this.sendJSONResponse(f, req, res, 200))
190201

191202
/**
192203
* @openapi
@@ -199,7 +210,9 @@ export class API {
199210
* description: Successfully deleted
200211
*/
201212
FLUSH = (req, res) =>
202-
this.index.FLUSH().then(idxRes => this.sendJSONResponse(idxRes, res))
213+
this.index
214+
.FLUSH()
215+
.then(idxRes => this.sendJSONResponse(idxRes, req, res, 200))
203216

204217
/**
205218
* @openapi
@@ -225,7 +238,7 @@ export class API {
225238
req.on('end', () =>
226239
this.index
227240
.IMPORT(JSON.parse(body))
228-
.then(idxRes => this.sendJSONResponse(idxRes, res))
241+
.then(idxRes => this.sendJSONResponse(idxRes, req, res, 200))
229242
)
230243
}
231244

@@ -244,7 +257,7 @@ export class API {
244257
MAX = (req, res) =>
245258
this.index
246259
.MAX(...this.params(req, 'TOKENSPACE'))
247-
.then(m => this.sendJSONResponse(m, res))
260+
.then(m => this.sendJSONResponse(m, req, res, 200))
248261

249262
/**
250263
* @openapi
@@ -261,7 +274,7 @@ export class API {
261274
MIN = (req, res) =>
262275
this.index
263276
.MIN(JSON.parse(this.params(req, 'TOKENSPACE'))) // TODO: is this right?
264-
.then(m => this.sendJSONResponse(m, res))
277+
.then(m => this.sendJSONResponse(m, req, res, 200))
265278

266279
/**
267280
* @openapi
@@ -331,12 +344,14 @@ export class API {
331344

332345
// curl -H "Content-Type: application/json" --data @testdata.json http://localhost:8081/put
333346
PUT = (req, res) => {
347+
console.log('I AM HEEEEEREEE IN PUT')
334348
let body = ''
335349
req.on('data', d => (body += d.toString()))
336350
req.on('end', () =>
337351
this.index
338352
.PUT(JSON.parse(body))
339-
.then(idxRes => this.sendJSONResponse(idxRes, res))
353+
.then(idxRes => this.sendJSONResponse(idxRes, req, res, 200))
354+
.catch(e => this.internalServerError(e, req, res))
340355
)
341356
}
342357

@@ -366,7 +381,7 @@ export class API {
366381
req.on('end', () =>
367382
this.index
368383
.PUT_RAW(JSON.parse(body))
369-
.then(idxRes => this.sendJSONResponse(idxRes, res))
384+
.then(idxRes => this.sendJSONResponse(idxRes, req, res, 200))
370385
)
371386
}
372387

@@ -462,7 +477,7 @@ export class API {
462477
SCORE: this.param(req, 'SCORE'),
463478
SORT: this.param(req, 'SORT')
464479
})
465-
.then(r => this.sendJSONResponse(r, res))
480+
.then(r => this.sendJSONResponse(r, req, res, 200))
466481

467482
/**
468483
* @openapi
@@ -497,7 +512,7 @@ export class API {
497512
.SEARCH(this.param(req, 'STRING').trim().split(/\s+/), {
498513
PAGE: this.param(req, 'PAGE')
499514
})
500-
.then(r => this.sendJSONResponse(r, res))
515+
.then(r => this.sendJSONResponse(r, req, res, 200))
501516

502517
/**
503518
* @openapi
@@ -523,7 +538,9 @@ export class API {
523538
CREATED: new Date(CREATED),
524539
LAST_UPDATED: new Date(LAST_UPDATED)
525540
},
526-
res
541+
req,
542+
res,
543+
200
527544
)
528545
)
529546

@@ -541,8 +558,8 @@ export class API {
541558
*/
542559
READY = (req, res) =>
543560
this.ready
544-
? this.sendJSONResponse({ READY: true }, res)
561+
? this.sendJSONResponse({ READY: true }, req, res, 200)
545562
: this.events.on('ready', () =>
546-
this.sendJSONResponse({ READY: true }, res)
547-
)
563+
this.sendJSONResponse({ READY: true }, req, res, 200)
564+
)
548565
}

src/Norch.js

+38-29
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { API } from './API.js'
55
import { SearchIndex } from 'search-index'
66
import { createServer } from 'node:http'
77
import { fileURLToPath } from 'url'
8-
import { readdirSync, readFileSync } from 'node:fs'
8+
import { createReadStream, readdirSync, readFileSync } from 'node:fs'
99
import { resolve, dirname } from 'path'
1010
import figlet from 'figlet'
1111

1212
export class Norch {
13-
constructor (ops = {}) {
13+
constructor(ops = {}) {
1414
const defaultConfigFile = JSON.parse(
1515
readFileSync(new URL('../defaultConfig.json', import.meta.url))
1616
)
@@ -22,7 +22,12 @@ export class Norch {
2222
this.splash(this.index, this.options.port)
2323
.then(() =>
2424
this.createNorchServer(
25-
new API(this.index, this.sendResponse, this.events)
25+
new API(
26+
this.index,
27+
this.sendResponse,
28+
this.events,
29+
this.logResponse
30+
)
2631
)
2732
)
2833
.then(server => {
@@ -34,6 +39,9 @@ export class Norch {
3439
})
3540
}
3641

42+
logResponse = (statusCode, path) =>
43+
console.info('[' + statusCode + '] ' + path)
44+
3745
readUserConfigFile = location => {
3846
// if no user config defined, simply return an empty object
3947
if (!location) return {}
@@ -50,7 +58,7 @@ export class Norch {
5058
index.CREATED(),
5159
index.DOCUMENT_COUNT()
5260
]).then(res =>
53-
console.log(
61+
console.info(
5462
`
5563
${figlet
5664
.textSync('NORCH', { font: 'Isometric1', horizontalLayout: 'full' })
@@ -69,32 +77,26 @@ export class Norch {
6977
)
7078

7179
sendResponse = (body, res, type) => {
72-
res.setHeader('Content-Type', type + '; charset=utf-8')
80+
res.setHeader('Content-Type', type)
7381
res.writeHead(200)
7482
res.end(body)
7583
}
7684

7785
createNorchServer = api =>
7886
createServer((req, res) => {
87+
// strip hostname, protocol, url-params, etc
7988
let pathname = new URL(req.url, `http://${req.headers.host}/`).pathname
80-
console.info(pathname)
81-
82-
if (req.method === 'GET') {
83-
const fileDirs = ['/', '/api/']
84-
85-
// default to index.html when only file-directory is specified
86-
if (fileDirs.includes(pathname)) pathname += 'index.html'
87-
88-
// Serve up static files files
89-
if (this.files(fileDirs).includes(pathname)) {
90-
console.log(dirname(fileURLToPath(import.meta.url)))
91-
return this.sendFileResponse(pathname, res)
92-
}
89+
// Serve up API requests
90+
if (pathname.split('/')[1] === 'API') {
91+
return api[pathname.split('/')[2]]
92+
? api[pathname.split('/')[2]](req, res)
93+
: this._404(res, pathname)
9394
}
9495

95-
return api[pathname.slice(1)]
96-
? api[pathname.slice(1)](req, res)
97-
: this._404(req, res)
96+
// serve up file requests (default to index.html when only file-directory
97+
// is specified)
98+
if (/^\/.*\/$|^\/$/.test(pathname)) pathname += 'index.html'
99+
return this.sendFileResponse(pathname, res)
98100
})
99101

100102
files = dirs => {
@@ -107,17 +109,24 @@ export class Norch {
107109
return dirs.map(d => getFilesInDir(d)).flat()
108110
}
109111

110-
sendFileResponse = (name, res) =>
111-
this.sendResponse(
112-
readFileSync(
113-
resolve(dirname(fileURLToPath(import.meta.url)), '../www_root' + name)
114-
) + '',
115-
res,
116-
mime.getType(name)
112+
sendFileResponse = (pathname, res) => {
113+
const s = createReadStream(
114+
resolve(dirname(fileURLToPath(import.meta.url)), '../www_root' + pathname)
117115
)
116+
s.on('open', () => {
117+
res.setHeader('Content-Type', mime.getType(pathname))
118+
s.pipe(res)
119+
console.info('[200] ' + pathname)
120+
})
121+
s.on('error', e => {
122+
// TODO: codes other than 404 here.
123+
this._404(res, pathname)
124+
})
125+
}
118126

119127
// ("404: page not found")
120-
_404 = (req, res) => {
128+
_404 = (res, pathname) => {
129+
console.info('[404] ' + pathname)
121130
res.setHeader('Content-Type', 'text/html; charset=utf-8')
122131
res.writeHead(404)
123132
res.end('<html><h1>404</h1>nothing here bro!</html>')

0 commit comments

Comments
 (0)