orator-static-server 2.0.0 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +50 -0
- package/README.md +11 -3
- package/docs/css/docuserve.css +73 -0
- package/docs/index.html +1 -1
- package/docs/retold-catalog.json +41 -0
- package/docs/retold-keyword-index.json +19 -0
- package/package.json +6 -6
- package/source/Orator-Static-Server.js +6 -9
- package/test/Orator-Static-Server_tests.js +169 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Contributing to Retold
|
|
2
|
+
|
|
3
|
+
We welcome contributions to Retold and its modules. This guide covers the expectations and process for contributing.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
The Retold community values **empathy**, **equity**, **kindness**, and **thoughtfulness**. We expect all participants to treat each other with respect, assume good intent, and engage constructively. These values apply to all interactions: pull requests, issues, discussions, and code review.
|
|
8
|
+
|
|
9
|
+
## How to Contribute
|
|
10
|
+
|
|
11
|
+
### Pull Requests
|
|
12
|
+
|
|
13
|
+
Pull requests are the preferred method for contributing changes. To submit one:
|
|
14
|
+
|
|
15
|
+
1. Fork the module repository you want to change
|
|
16
|
+
2. Create a branch for your work
|
|
17
|
+
3. Make your changes, following the code style of the module you are editing
|
|
18
|
+
4. Ensure your changes have test coverage (see below)
|
|
19
|
+
5. Open a pull request against the module's main branch
|
|
20
|
+
|
|
21
|
+
**Submitting a pull request does not guarantee it will be accepted.** Maintainers review contributions for fit, quality, and alignment with the project's direction. A PR may be declined, or you may be asked to revise it. This is normal and not a reflection on the quality of your effort.
|
|
22
|
+
|
|
23
|
+
### Reporting Issues
|
|
24
|
+
|
|
25
|
+
If you find a bug or have a feature suggestion, open an issue on the relevant module's repository. Include enough detail to reproduce the problem or understand the proposal.
|
|
26
|
+
|
|
27
|
+
## Test Coverage
|
|
28
|
+
|
|
29
|
+
Every commit must include test coverage for the changes it introduces. Retold modules use Mocha in TDD style. Before submitting:
|
|
30
|
+
|
|
31
|
+
- **Write tests** for any new functionality or bug fixes
|
|
32
|
+
- **Run the existing test suite** with `npm test` and confirm all tests pass
|
|
33
|
+
- **Check coverage** with `npm run coverage` if the module supports it
|
|
34
|
+
|
|
35
|
+
Pull requests that break existing tests or lack coverage for new code will not be merged.
|
|
36
|
+
|
|
37
|
+
## Code Style
|
|
38
|
+
|
|
39
|
+
Follow the conventions of the module you are working in. The general Retold style is:
|
|
40
|
+
|
|
41
|
+
- **Tabs** for indentation, never spaces
|
|
42
|
+
- **Plain JavaScript** only (no TypeScript)
|
|
43
|
+
- **Allman-style braces** (opening brace on its own line)
|
|
44
|
+
- **Variable naming:** `pVariable` for parameters, `tmpVariable` for temporaries, `libSomething` for imports
|
|
45
|
+
|
|
46
|
+
When in doubt, match what the surrounding code does.
|
|
47
|
+
|
|
48
|
+
## Repository Structure
|
|
49
|
+
|
|
50
|
+
Each module is its own git repository. The [retold](https://github.com/stevenvelozo/retold) repository tracks module organization but does not contain module source code. Direct your pull request to the specific module repository where your change belongs.
|
package/README.md
CHANGED
|
@@ -99,6 +99,14 @@ npx docsify-cli serve docs
|
|
|
99
99
|
|
|
100
100
|
## Related Packages
|
|
101
101
|
|
|
102
|
-
- [orator](https://github.com/stevenvelozo/orator) -
|
|
103
|
-
- [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server
|
|
104
|
-
- [fable](https://github.com/stevenvelozo/fable) -
|
|
102
|
+
- [orator](https://github.com/stevenvelozo/orator) - API server abstraction
|
|
103
|
+
- [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server implementation
|
|
104
|
+
- [fable](https://github.com/stevenvelozo/fable) - Application services framework
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|
|
109
|
+
|
|
110
|
+
## Contributing
|
|
111
|
+
|
|
112
|
+
Pull requests are welcome. For details on our code of conduct, contribution process, and testing requirements, see the [Retold Contributing Guide](https://github.com/stevenvelozo/retold/blob/main/docs/contributing.md).
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
Pict Docuserve - Base Styles
|
|
3
|
+
============================================================================ */
|
|
4
|
+
|
|
5
|
+
/* Reset and base */
|
|
6
|
+
*, *::before, *::after {
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
html, body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
14
|
+
font-size: 16px;
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
color: #423D37;
|
|
17
|
+
background-color: #fff;
|
|
18
|
+
-webkit-font-smoothing: antialiased;
|
|
19
|
+
-moz-osx-font-smoothing: grayscale;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Typography */
|
|
23
|
+
h1, h2, h3, h4, h5, h6 {
|
|
24
|
+
margin-top: 0;
|
|
25
|
+
line-height: 1.3;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
a {
|
|
29
|
+
color: #2E7D74;
|
|
30
|
+
text-decoration: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a:hover {
|
|
34
|
+
color: #256861;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Application container */
|
|
38
|
+
#Docuserve-Application-Container {
|
|
39
|
+
min-height: 100vh;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Utility: scrollbar styling */
|
|
43
|
+
::-webkit-scrollbar {
|
|
44
|
+
width: 8px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::-webkit-scrollbar-track {
|
|
48
|
+
background: #F5F0E8;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
::-webkit-scrollbar-thumb {
|
|
52
|
+
background: #D4CCBE;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
::-webkit-scrollbar-thumb:hover {
|
|
57
|
+
background: #B5AA9A;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Responsive adjustments */
|
|
61
|
+
@media (max-width: 768px) {
|
|
62
|
+
html {
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#Docuserve-Sidebar-Container {
|
|
67
|
+
display: none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.docuserve-body {
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
}
|
|
73
|
+
}
|
package/docs/index.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<title>Documentation</title>
|
|
10
10
|
|
|
11
11
|
<!-- Application Stylesheet -->
|
|
12
|
-
<link href="
|
|
12
|
+
<link href="css/docuserve.css" rel="stylesheet">
|
|
13
13
|
<!-- KaTeX stylesheet for LaTeX equation rendering -->
|
|
14
14
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css">
|
|
15
15
|
<!-- PICT Dynamic View CSS Container -->
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Generated": "2026-02-18T03:41:38.903Z",
|
|
3
|
+
"GitHubOrg": "stevenvelozo",
|
|
4
|
+
"DefaultBranch": "master",
|
|
5
|
+
"Groups": [
|
|
6
|
+
{
|
|
7
|
+
"Name": "Dist",
|
|
8
|
+
"Key": "dist",
|
|
9
|
+
"Description": "",
|
|
10
|
+
"Modules": [
|
|
11
|
+
{
|
|
12
|
+
"Name": "indoctrinate_content_staging",
|
|
13
|
+
"Repo": "indoctrinate_content_staging",
|
|
14
|
+
"Group": "dist",
|
|
15
|
+
"Branch": "master",
|
|
16
|
+
"HasDocs": false,
|
|
17
|
+
"HasCover": false,
|
|
18
|
+
"Sidebar": [],
|
|
19
|
+
"DocFiles": []
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"Name": "Test",
|
|
25
|
+
"Key": "test",
|
|
26
|
+
"Description": "",
|
|
27
|
+
"Modules": [
|
|
28
|
+
{
|
|
29
|
+
"Name": "static_content",
|
|
30
|
+
"Repo": "static_content",
|
|
31
|
+
"Group": "test",
|
|
32
|
+
"Branch": "master",
|
|
33
|
+
"HasDocs": false,
|
|
34
|
+
"HasCover": false,
|
|
35
|
+
"Sidebar": [],
|
|
36
|
+
"DocFiles": []
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Generated": "2026-02-18T03:41:38.985Z",
|
|
3
|
+
"DocumentCount": 0,
|
|
4
|
+
"LunrIndex": {
|
|
5
|
+
"version": "2.3.9",
|
|
6
|
+
"fields": [
|
|
7
|
+
"title",
|
|
8
|
+
"module",
|
|
9
|
+
"group",
|
|
10
|
+
"body"
|
|
11
|
+
],
|
|
12
|
+
"fieldVectors": [],
|
|
13
|
+
"invertedIndex": [],
|
|
14
|
+
"pipeline": [
|
|
15
|
+
"stemmer"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"Documents": {}
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orator-static-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Static file serving for Orator API servers.",
|
|
5
5
|
"main": "source/Orator-Static-Server.js",
|
|
6
6
|
"scripts": {
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://github.com/stevenvelozo/orator-static-server#readme",
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"fable-serviceproviderbase": "^3.0.
|
|
41
|
+
"fable-serviceproviderbase": "^3.0.18",
|
|
42
42
|
"finalhandler": "^1.3.1",
|
|
43
43
|
"mime": "^3.0.0",
|
|
44
44
|
"serve-static": "^1.16.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"chai": "^4.3.7",
|
|
48
|
-
"fable": "^3.1.
|
|
48
|
+
"fable": "^3.1.57",
|
|
49
49
|
"mocha": "^10.2.0",
|
|
50
|
-
"orator": "^
|
|
51
|
-
"orator-serviceserver-restify": "^2.0.
|
|
52
|
-
"quackage": "^1.0.
|
|
50
|
+
"orator": "^6.0.1",
|
|
51
|
+
"orator-serviceserver-restify": "^2.0.7",
|
|
52
|
+
"quackage": "^1.0.51"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -161,15 +161,12 @@ class OratorStaticServer extends libFableServiceProviderBase
|
|
|
161
161
|
return pRequest.url;
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
this.setMimeHeader(tmpMimeTarget, pResponse);
|
|
172
|
-
|
|
164
|
+
// Let serve-static handle Content-Type detection. It resolves
|
|
165
|
+
// the actual file path first (e.g. / → /index.html) and then
|
|
166
|
+
// sets the correct MIME type with charset. Pre-setting the
|
|
167
|
+
// header here would prevent serve-static from overriding it
|
|
168
|
+
// because the underlying `send` library skips Content-Type
|
|
169
|
+
// when the header is already present.
|
|
173
170
|
const tmpServe = libServeStatic(servePath, Object.assign({ index: tmpDefaultFile }, pParams));
|
|
174
171
|
tmpServe(pRequest, pResponse, libFinalHandler(pRequest, pResponse));
|
|
175
172
|
// TODO: This may break things if a post request send handler is setup...
|
|
@@ -1308,6 +1308,175 @@ suite
|
|
|
1308
1308
|
}
|
|
1309
1309
|
);
|
|
1310
1310
|
|
|
1311
|
+
suite
|
|
1312
|
+
(
|
|
1313
|
+
'MIME Type Resolution by serve-static',
|
|
1314
|
+
() =>
|
|
1315
|
+
{
|
|
1316
|
+
test
|
|
1317
|
+
(
|
|
1318
|
+
'serve-static should set content-type with charset for HTML files',
|
|
1319
|
+
(fDone) =>
|
|
1320
|
+
{
|
|
1321
|
+
let tmpPort = getNextTestPort();
|
|
1322
|
+
let tmpHarness = createHarness(tmpPort);
|
|
1323
|
+
|
|
1324
|
+
startHarness(tmpHarness,
|
|
1325
|
+
(pError) =>
|
|
1326
|
+
{
|
|
1327
|
+
tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/mime/*', '/mime/');
|
|
1328
|
+
|
|
1329
|
+
makeRequest(tmpPort, '/mime/index.html',
|
|
1330
|
+
(pError, pStatusCode, pHeaders, pBody) =>
|
|
1331
|
+
{
|
|
1332
|
+
Expect(pError).to.equal(null);
|
|
1333
|
+
Expect(pStatusCode).to.equal(200);
|
|
1334
|
+
// serve-static sets charset on text types; a manual setMimeHeader would not
|
|
1335
|
+
Expect(pHeaders['content-type']).to.equal('text/html; charset=UTF-8');
|
|
1336
|
+
tmpHarness.orator.log.info(`HTML content-type with charset: ${pHeaders['content-type']}`);
|
|
1337
|
+
tmpHarness.orator.stopService(
|
|
1338
|
+
() =>
|
|
1339
|
+
{
|
|
1340
|
+
return fDone();
|
|
1341
|
+
});
|
|
1342
|
+
});
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
);
|
|
1346
|
+
|
|
1347
|
+
test
|
|
1348
|
+
(
|
|
1349
|
+
'serve-static should set content-type with charset for CSS files',
|
|
1350
|
+
(fDone) =>
|
|
1351
|
+
{
|
|
1352
|
+
let tmpPort = getNextTestPort();
|
|
1353
|
+
let tmpHarness = createHarness(tmpPort);
|
|
1354
|
+
|
|
1355
|
+
startHarness(tmpHarness,
|
|
1356
|
+
(pError) =>
|
|
1357
|
+
{
|
|
1358
|
+
tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/mimecss/*', '/mimecss/');
|
|
1359
|
+
|
|
1360
|
+
makeRequest(tmpPort, '/mimecss/style.css',
|
|
1361
|
+
(pError, pStatusCode, pHeaders, pBody) =>
|
|
1362
|
+
{
|
|
1363
|
+
Expect(pError).to.equal(null);
|
|
1364
|
+
Expect(pStatusCode).to.equal(200);
|
|
1365
|
+
// serve-static adds charset for text/* types
|
|
1366
|
+
Expect(pHeaders['content-type']).to.equal('text/css; charset=UTF-8');
|
|
1367
|
+
tmpHarness.orator.log.info(`CSS content-type with charset: ${pHeaders['content-type']}`);
|
|
1368
|
+
tmpHarness.orator.stopService(
|
|
1369
|
+
() =>
|
|
1370
|
+
{
|
|
1371
|
+
return fDone();
|
|
1372
|
+
});
|
|
1373
|
+
});
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
);
|
|
1377
|
+
|
|
1378
|
+
test
|
|
1379
|
+
(
|
|
1380
|
+
'directory request to / should get text/html from serve-static not application/octet-stream',
|
|
1381
|
+
(fDone) =>
|
|
1382
|
+
{
|
|
1383
|
+
let tmpPort = getNextTestPort();
|
|
1384
|
+
let tmpHarness = createHarness(tmpPort);
|
|
1385
|
+
|
|
1386
|
+
startHarness(tmpHarness,
|
|
1387
|
+
(pError) =>
|
|
1388
|
+
{
|
|
1389
|
+
tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/*', '/');
|
|
1390
|
+
|
|
1391
|
+
makeRequest(tmpPort, '/',
|
|
1392
|
+
(pError, pStatusCode, pHeaders, pBody) =>
|
|
1393
|
+
{
|
|
1394
|
+
Expect(pError).to.equal(null);
|
|
1395
|
+
Expect(pStatusCode).to.equal(200);
|
|
1396
|
+
// The core bug: mime.getType('/') returns null, falling back to
|
|
1397
|
+
// application/octet-stream. serve-static resolves / to /index.html
|
|
1398
|
+
// and correctly determines text/html with charset.
|
|
1399
|
+
Expect(pHeaders['content-type']).to.equal('text/html; charset=UTF-8');
|
|
1400
|
+
Expect(pHeaders['content-type']).to.not.contain('octet-stream');
|
|
1401
|
+
Expect(pBody).to.contain('Test Index');
|
|
1402
|
+
tmpHarness.orator.log.info(`Root / content-type: ${pHeaders['content-type']}`);
|
|
1403
|
+
tmpHarness.orator.stopService(
|
|
1404
|
+
() =>
|
|
1405
|
+
{
|
|
1406
|
+
return fDone();
|
|
1407
|
+
});
|
|
1408
|
+
});
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
);
|
|
1412
|
+
|
|
1413
|
+
test
|
|
1414
|
+
(
|
|
1415
|
+
'directory request to /subdir/ should get text/html from serve-static',
|
|
1416
|
+
(fDone) =>
|
|
1417
|
+
{
|
|
1418
|
+
let tmpPort = getNextTestPort();
|
|
1419
|
+
let tmpHarness = createHarness(tmpPort);
|
|
1420
|
+
|
|
1421
|
+
startHarness(tmpHarness,
|
|
1422
|
+
(pError) =>
|
|
1423
|
+
{
|
|
1424
|
+
tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/app/*', '/app/');
|
|
1425
|
+
|
|
1426
|
+
makeRequest(tmpPort, '/app/subsite/',
|
|
1427
|
+
(pError, pStatusCode, pHeaders, pBody) =>
|
|
1428
|
+
{
|
|
1429
|
+
Expect(pError).to.equal(null);
|
|
1430
|
+
Expect(pStatusCode).to.equal(200);
|
|
1431
|
+
// serve-static resolves /subsite/ to /subsite/index.html
|
|
1432
|
+
Expect(pHeaders['content-type']).to.equal('text/html; charset=UTF-8');
|
|
1433
|
+
Expect(pBody).to.contain('Subsite');
|
|
1434
|
+
tmpHarness.orator.log.info(`Subdir / content-type: ${pHeaders['content-type']}`);
|
|
1435
|
+
tmpHarness.orator.stopService(
|
|
1436
|
+
() =>
|
|
1437
|
+
{
|
|
1438
|
+
return fDone();
|
|
1439
|
+
});
|
|
1440
|
+
});
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
);
|
|
1444
|
+
|
|
1445
|
+
test
|
|
1446
|
+
(
|
|
1447
|
+
'JSON file should get application/json content-type from serve-static',
|
|
1448
|
+
(fDone) =>
|
|
1449
|
+
{
|
|
1450
|
+
let tmpPort = getNextTestPort();
|
|
1451
|
+
let tmpHarness = createHarness(tmpPort);
|
|
1452
|
+
|
|
1453
|
+
startHarness(tmpHarness,
|
|
1454
|
+
(pError) =>
|
|
1455
|
+
{
|
|
1456
|
+
tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/mj/*', '/mj/');
|
|
1457
|
+
|
|
1458
|
+
makeRequest(tmpPort, '/mj/data.json',
|
|
1459
|
+
(pError, pStatusCode, pHeaders, pBody) =>
|
|
1460
|
+
{
|
|
1461
|
+
Expect(pError).to.equal(null);
|
|
1462
|
+
Expect(pStatusCode).to.equal(200);
|
|
1463
|
+
// JSON should not have charset added by serve-static
|
|
1464
|
+
Expect(pHeaders['content-type']).to.contain('application/json');
|
|
1465
|
+
let tmpParsed = JSON.parse(pBody);
|
|
1466
|
+
Expect(tmpParsed.TestKey).to.equal('TestValue');
|
|
1467
|
+
tmpHarness.orator.log.info(`JSON content-type: ${pHeaders['content-type']}`);
|
|
1468
|
+
tmpHarness.orator.stopService(
|
|
1469
|
+
() =>
|
|
1470
|
+
{
|
|
1471
|
+
return fDone();
|
|
1472
|
+
});
|
|
1473
|
+
});
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1478
|
+
);
|
|
1479
|
+
|
|
1311
1480
|
suite
|
|
1312
1481
|
(
|
|
1313
1482
|
'addStaticRoute Parameter Defaults',
|