Non gemtext static files
* Static file handler now attempts to use "file-type" if it is available to read the magic bytes of a file and get Mime type * Fixed a crash if the client closed the socket prematurely * Move README to gmi
This commit is contained in:
parent
7761c18fd5
commit
2dabbc0969
|
@ -1 +1,2 @@
|
||||||
*.pem
|
*.pem
|
||||||
|
node_modules
|
||||||
|
|
|
@ -220,6 +220,9 @@ export default class GeminiServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// This can be just ECONNRESET
|
||||||
|
socket.on("error", console.error);
|
||||||
});
|
});
|
||||||
server.listen(1965);
|
server.listen(1965);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ A `relativePath` is the difference between a `basePath` and a `urlPath`. It's no
|
||||||
|
|
||||||
Sometimes these paths will include their hostnames
|
Sometimes these paths will include their hostnames
|
||||||
|
|
||||||
A path in the pathRegistry is a `p`, which is an object with a hostname, a basePath, and a handler
|
A path in the pathRegistry is a `p`, which is an object with a hostname, a basePath, and a handler
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,4 +44,4 @@ openssl x509 -req -in csr.pem -signkey private-key.pem -out public-cert.pem
|
||||||
It's possible to imagine a situation where astronomical theater is behind a proxy and the proxy doesn't do address translation, passing the raw gemini request to us.
|
It's possible to imagine a situation where astronomical theater is behind a proxy and the proxy doesn't do address translation, passing the raw gemini request to us.
|
||||||
In this case, our behavior is undefined.
|
In this case, our behavior is undefined.
|
||||||
|
|
||||||
Similarly, SNI is not supported with IP addresses.
|
Similarly, SNI is not supported with IP addresses.
|
|
@ -57,8 +57,8 @@ server.registerPath("localhost/allFiles", new ExampleHandler());
|
||||||
// We will provide some convenient handlers for static, CGI, and reverse proxy
|
// We will provide some convenient handlers for static, CGI, and reverse proxy
|
||||||
|
|
||||||
//if the passed file is a single file, it's a file. If it's a directory, all sub-files are auto-included
|
//if the passed file is a single file, it's a file. If it's a directory, all sub-files are auto-included
|
||||||
server.registerPath("localhost/static/about.gmi", new StaticHandler("/tmp/content/about.gmi" /*, {options}*/));
|
server.registerPath("localhost/static/about.gmi", new StaticHandler("README.gmi" /*, {options}*/));
|
||||||
server.registerPath("localhost/static", new StaticHandler("/tmp/content/" /*, {options}*/));
|
server.registerPath("localhost/static", new StaticHandler("static/" /*, {options}*/));
|
||||||
// server.registerPath("localhost/static", new StaticHandler("/tmp/yourmom/" /*, {options}*/));
|
// server.registerPath("localhost/static", new StaticHandler("/tmp/yourmom/" /*, {options}*/));
|
||||||
|
|
||||||
//The file passed to CGI handler must exist and be executable at run time
|
//The file passed to CGI handler must exist and be executable at run time
|
||||||
|
|
|
@ -3,6 +3,9 @@ import * as fs from "fs";
|
||||||
|
|
||||||
import DefaultHandler from "./default.js";
|
import DefaultHandler from "./default.js";
|
||||||
|
|
||||||
|
let fileTypeFromFile;
|
||||||
|
import("file-type").then(ft => fileTypeFromFile = ft.default.fromFile).catch(console.error);
|
||||||
|
|
||||||
export default class StaticHandler extends DefaultHandler {
|
export default class StaticHandler extends DefaultHandler {
|
||||||
constructor(basePath, directoryList = false) {
|
constructor(basePath, directoryList = false) {
|
||||||
super();
|
super();
|
||||||
|
@ -18,7 +21,7 @@ export default class StaticHandler extends DefaultHandler {
|
||||||
|
|
||||||
// This is the handler
|
// This is the handler
|
||||||
// url is the URL object, with url.pathname being the path. p is the 'client-side' basepath
|
// url is the URL object, with url.pathname being the path. p is the 'client-side' basepath
|
||||||
handle (url, p) {
|
async handle (url, p, socket) {
|
||||||
const relativePath = path.relative(p, url.pathname);
|
const relativePath = path.relative(p, url.pathname);
|
||||||
//Concat and normalize the passed URL as being relative to the base path
|
//Concat and normalize the passed URL as being relative to the base path
|
||||||
const toServe = path.join(this.basePath, relativePath);
|
const toServe = path.join(this.basePath, relativePath);
|
||||||
|
@ -32,7 +35,7 @@ export default class StaticHandler extends DefaultHandler {
|
||||||
if (fs.statSync(toServe).isDirectory()) {
|
if (fs.statSync(toServe).isDirectory()) {
|
||||||
console.log(`File is a directory and directoryList is ${this.directoryList}.`);
|
console.log(`File is a directory and directoryList is ${this.directoryList}.`);
|
||||||
if (this.directoryList) {
|
if (this.directoryList) {
|
||||||
|
//TODO: Static content directory listing
|
||||||
} else {
|
} else {
|
||||||
return "51 Not Found\r\n";
|
return "51 Not Found\r\n";
|
||||||
}
|
}
|
||||||
|
@ -43,9 +46,31 @@ export default class StaticHandler extends DefaultHandler {
|
||||||
return "51 Not Found\r\n";
|
return "51 Not Found\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: import mmmagic
|
let mimeType = "text/gemini";
|
||||||
|
|
||||||
|
if (fileTypeFromFile) {
|
||||||
|
const type = await fileTypeFromFile(toServe);
|
||||||
|
// `type` will be undefined if the file is plaintext
|
||||||
|
// In which case we want to fall down to serving plaintext
|
||||||
|
if (type) {
|
||||||
|
mimeType = type.mime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: some file-ending based logic, please
|
||||||
|
//So we can serve md and txt
|
||||||
|
|
||||||
|
|
||||||
//TODO: convert line endings
|
//TODO: convert line endings
|
||||||
const data = fs.readFileSync(toServe);
|
// I read somewhere that `readFileSync` on every request is a bad idea, but I don't care
|
||||||
return "20 text/gemini\r\n" + data;
|
socket.write(`20 ${mimeType}\r\n`);
|
||||||
|
const fileReader = fs.createReadStream(toServe);
|
||||||
|
//This function (handle) needs to return after we're done writing the file to the stream
|
||||||
|
//Because the place that called this is going to handle .end() the socket
|
||||||
|
//So we don't end the socket here, and we make a promise to wait for the reader to end before returning
|
||||||
|
//It would be great if we could just not return from this function but I don't think that's how this works
|
||||||
|
fileReader.pipe(socket, {end: false});
|
||||||
|
await new Promise((res, rej) => fileReader.on("end", res));
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,275 @@
|
||||||
|
{
|
||||||
|
"name": "astronomical-theater",
|
||||||
|
"version": "v2.0.5",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "astronomical-theater",
|
||||||
|
"version": "v2.0.5",
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"optionalDependencies": {
|
||||||
|
"file-type": "^16.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tokenizer/token": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/file-type": {
|
||||||
|
"version": "16.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.3.tgz",
|
||||||
|
"integrity": "sha512-uVsl7iFhHSOY4bEONLlTK47iAHtNsFHWP5YE4xJfZ4rnX7S1Q3wce09XgqSC7E/xh8Ncv/be1lNoyprlUH/x6A==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"readable-web-to-node-stream": "^3.0.0",
|
||||||
|
"strtok3": "^6.2.4",
|
||||||
|
"token-types": "^4.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/peek-readable": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-7qmhptnR0WMSpxT5rMHG9bW/mYSR1uqaPFj2MHvT+y/aOUu6msJijpKt5SkTDKySwg65OWG2JwTMBlgcbwMHrQ==",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-web-to-node-stream": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": "^3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strtok3": {
|
||||||
|
"version": "6.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz",
|
||||||
|
"integrity": "sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"peek-readable": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/token-types": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/token-types/-/token-types-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-hD+QyuUAyI2spzsI0B7gf/jJ2ggR4RjkAo37j3StuePhApJUwcWDjnHDOFdIWYSwNR28H14hpwm4EI+V1Ted1w==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"ieee754": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tokenizer/token": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"file-type": {
|
||||||
|
"version": "16.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.3.tgz",
|
||||||
|
"integrity": "sha512-uVsl7iFhHSOY4bEONLlTK47iAHtNsFHWP5YE4xJfZ4rnX7S1Q3wce09XgqSC7E/xh8Ncv/be1lNoyprlUH/x6A==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"readable-web-to-node-stream": "^3.0.0",
|
||||||
|
"strtok3": "^6.2.4",
|
||||||
|
"token-types": "^4.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"peek-readable": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-7qmhptnR0WMSpxT5rMHG9bW/mYSR1uqaPFj2MHvT+y/aOUu6msJijpKt5SkTDKySwg65OWG2JwTMBlgcbwMHrQ==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readable-web-to-node-stream": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"readable-stream": "^3.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strtok3": {
|
||||||
|
"version": "6.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz",
|
||||||
|
"integrity": "sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"peek-readable": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"token-types": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/token-types/-/token-types-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-hD+QyuUAyI2spzsI0B7gf/jJ2ggR4RjkAo37j3StuePhApJUwcWDjnHDOFdIWYSwNR28H14hpwm4EI+V1Ted1w==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"ieee754": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "astronomical-theater",
|
"name": "astronomical-theater",
|
||||||
"version": "v2.0.5",
|
"version": "v2.1.0",
|
||||||
"author": "Matthias",
|
"author": "Matthias",
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node main.js"
|
"start": "node main.js"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"file-type": "^16.5.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Loading…
Reference in New Issue