@telepath-computer/autofile 0.0.0-stage → 0.3.0
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/LICENSE +21 -0
- package/README.md +74 -2
- package/dist/blobs.d.ts +34 -0
- package/dist/blobs.js +295 -0
- package/dist/blobs.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +180 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.js +258 -0
- package/dist/config.js.map +1 -0
- package/dist/http.d.ts +10 -0
- package/dist/http.js +152 -0
- package/dist/http.js.map +1 -0
- package/dist/json.d.ts +9 -0
- package/dist/json.js +3 -0
- package/dist/json.js.map +1 -0
- package/dist/schema.d.ts +25 -0
- package/dist/schema.js +235 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +237 -0
- package/dist/server.js.map +1 -0
- package/dist/store.d.ts +132 -0
- package/dist/store.js +1381 -0
- package/dist/store.js.map +1 -0
- package/dist/watch.d.ts +20 -0
- package/dist/watch.js +313 -0
- package/dist/watch.js.map +1 -0
- package/package.json +46 -4
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Reads, validates, and writes Autofile's process-wide settings. */
|
|
2
|
+
declare const settingNames: readonly ["storage", "http.host", "http.port", "http.origins"];
|
|
3
|
+
export type SettingName = typeof settingNames[number];
|
|
4
|
+
export interface HttpSettings {
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
origins: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface Settings {
|
|
10
|
+
storage: string;
|
|
11
|
+
http: HttpSettings;
|
|
12
|
+
}
|
|
13
|
+
/** Returns whether a command argument names one of Autofile's settings. */
|
|
14
|
+
export declare function isSettingName(value: string): value is SettingName;
|
|
15
|
+
/** Returns the path shared stores use to serialize writes between processes. */
|
|
16
|
+
export declare function getWriteLockPath(): string;
|
|
17
|
+
/** Returns every effective setting, applying defaults to settings that are absent. */
|
|
18
|
+
export declare function getSettings(): Promise<Settings>;
|
|
19
|
+
/** Returns the configured data folder, or the default folder when unset. */
|
|
20
|
+
export declare function getStorage(): Promise<string>;
|
|
21
|
+
/** Returns a setting as the lines its CLI `get` command prints. */
|
|
22
|
+
export declare function getSetting(name: SettingName): Promise<string[]>;
|
|
23
|
+
/** Validates and stores one setting while preserving every other setting. */
|
|
24
|
+
export declare function setSetting(name: SettingName, values: string[]): Promise<void>;
|
|
25
|
+
/** Removes one setting so its default applies, preserving its siblings. */
|
|
26
|
+
export declare function unsetSetting(name: SettingName): Promise<void>;
|
|
27
|
+
/** Parses a CLI port value and rejects anything outside the TCP port range. */
|
|
28
|
+
export declare function parsePort(value: string): number;
|
|
29
|
+
/** Returns the URL-normalized form of a strict HTTP origin, or undefined when invalid. */
|
|
30
|
+
export declare function normalizeHttpOrigin(value: string): string | undefined;
|
|
31
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/** Reads, validates, and writes Autofile's process-wide settings. */
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
const DEFAULT_HTTP_HOST = "127.0.0.1";
|
|
6
|
+
const DEFAULT_HTTP_PORT = 7319;
|
|
7
|
+
const settingNames = ["storage", "http.host", "http.port", "http.origins"];
|
|
8
|
+
function getAutofileHome() {
|
|
9
|
+
return resolve(process.env.AUTOFILE_HOME ?? join(homedir(), ".autofile"));
|
|
10
|
+
}
|
|
11
|
+
/** Returns whether a command argument names one of Autofile's settings. */
|
|
12
|
+
export function isSettingName(value) {
|
|
13
|
+
return settingNames.includes(value);
|
|
14
|
+
}
|
|
15
|
+
/** Returns the path shared stores use to serialize writes between processes. */
|
|
16
|
+
export function getWriteLockPath() {
|
|
17
|
+
return join(getAutofileHome(), "write.lock");
|
|
18
|
+
}
|
|
19
|
+
async function readConfig() {
|
|
20
|
+
const configPath = join(getAutofileHome(), "config.json");
|
|
21
|
+
let text;
|
|
22
|
+
try {
|
|
23
|
+
text = await readFile(configPath, "utf8");
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
27
|
+
return {};
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
let value;
|
|
31
|
+
try {
|
|
32
|
+
value = JSON.parse(text);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
throw new Error(`${configPath}: invalid JSON`);
|
|
36
|
+
}
|
|
37
|
+
if (!isObject(value))
|
|
38
|
+
throw new Error(`${configPath}: must contain a JSON object`);
|
|
39
|
+
const storage = "storage" in value ? value.storage : undefined;
|
|
40
|
+
if (storage !== undefined && typeof storage !== "string") {
|
|
41
|
+
throw new Error(`${configPath}: storage must be a string`);
|
|
42
|
+
}
|
|
43
|
+
const httpValue = "http" in value ? value.http : undefined;
|
|
44
|
+
if (httpValue !== undefined && !isObject(httpValue)) {
|
|
45
|
+
throw new Error(`${configPath}: http must be a JSON object`);
|
|
46
|
+
}
|
|
47
|
+
const host = httpValue === undefined || !("host" in httpValue) ? undefined : httpValue.host;
|
|
48
|
+
if (host !== undefined && (typeof host !== "string" || host.length === 0)) {
|
|
49
|
+
throw new Error(`${configPath}: http.host must be a non-empty string`);
|
|
50
|
+
}
|
|
51
|
+
const port = httpValue === undefined || !("port" in httpValue) ? undefined : httpValue.port;
|
|
52
|
+
if (port !== undefined && !isPort(port)) {
|
|
53
|
+
throw new Error(`${configPath}: http.port must be an integer from 1 to 65535`);
|
|
54
|
+
}
|
|
55
|
+
const originsValue = httpValue === undefined || !("origins" in httpValue)
|
|
56
|
+
? undefined
|
|
57
|
+
: httpValue.origins;
|
|
58
|
+
let origins;
|
|
59
|
+
if (originsValue !== undefined && !Array.isArray(originsValue)) {
|
|
60
|
+
throw new Error(`${configPath}: http.origins must contain only http or https origins without paths`);
|
|
61
|
+
}
|
|
62
|
+
if (originsValue !== undefined) {
|
|
63
|
+
origins = [];
|
|
64
|
+
for (const origin of originsValue) {
|
|
65
|
+
const normalized = typeof origin === "string" ? normalizeHttpOrigin(origin) : undefined;
|
|
66
|
+
if (normalized === undefined) {
|
|
67
|
+
throw new Error(`${configPath}: http.origins must contain only http or https origins without paths`);
|
|
68
|
+
}
|
|
69
|
+
origins.push(normalized);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
...(storage === undefined ? {} : { storage }),
|
|
74
|
+
...(host === undefined && port === undefined && origins === undefined
|
|
75
|
+
? {}
|
|
76
|
+
: {
|
|
77
|
+
http: {
|
|
78
|
+
...(host === undefined ? {} : { host }),
|
|
79
|
+
...(port === undefined ? {} : { port }),
|
|
80
|
+
...(origins === undefined ? {} : { origins }),
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function writeConfig(config) {
|
|
86
|
+
const autofileHome = getAutofileHome();
|
|
87
|
+
await mkdir(autofileHome, { recursive: true });
|
|
88
|
+
await writeFile(join(autofileHome, "config.json"), `${JSON.stringify(canonicalConfig(config), null, 2)}\n`, "utf8");
|
|
89
|
+
}
|
|
90
|
+
/** Returns every effective setting, applying defaults to settings that are absent. */
|
|
91
|
+
export async function getSettings() {
|
|
92
|
+
const config = await readConfig();
|
|
93
|
+
return {
|
|
94
|
+
storage: config.storage ?? join(getAutofileHome(), "data"),
|
|
95
|
+
http: {
|
|
96
|
+
host: config.http?.host ?? DEFAULT_HTTP_HOST,
|
|
97
|
+
port: config.http?.port ?? DEFAULT_HTTP_PORT,
|
|
98
|
+
origins: [...(config.http?.origins ?? [])],
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Returns the configured data folder, or the default folder when unset. */
|
|
103
|
+
export async function getStorage() {
|
|
104
|
+
return (await getSettings()).storage;
|
|
105
|
+
}
|
|
106
|
+
/** Returns a setting as the lines its CLI `get` command prints. */
|
|
107
|
+
export async function getSetting(name) {
|
|
108
|
+
const settings = await getSettings();
|
|
109
|
+
switch (name) {
|
|
110
|
+
case "storage": return [settings.storage];
|
|
111
|
+
case "http.host": return [settings.http.host];
|
|
112
|
+
case "http.port": return [String(settings.http.port)];
|
|
113
|
+
case "http.origins": return settings.http.origins;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Validates and stores one setting while preserving every other setting. */
|
|
117
|
+
export async function setSetting(name, values) {
|
|
118
|
+
const config = await readConfig();
|
|
119
|
+
switch (name) {
|
|
120
|
+
case "storage": {
|
|
121
|
+
const [folder] = values;
|
|
122
|
+
if (values.length !== 1 || folder === undefined || folder === "") {
|
|
123
|
+
throw new Error("storage must be a non-empty folder");
|
|
124
|
+
}
|
|
125
|
+
config.storage = resolveStorage(folder);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case "http.host": {
|
|
129
|
+
const [host] = values;
|
|
130
|
+
if (values.length !== 1 || host === undefined || host === "") {
|
|
131
|
+
throw new Error("http.host must be a non-empty string");
|
|
132
|
+
}
|
|
133
|
+
config.http = { ...config.http, host };
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case "http.port": {
|
|
137
|
+
const [value] = values;
|
|
138
|
+
if (values.length !== 1 || value === undefined) {
|
|
139
|
+
throw new Error("http.port must be an integer from 1 to 65535");
|
|
140
|
+
}
|
|
141
|
+
config.http = { ...config.http, port: parsePort(value) };
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case "http.origins": {
|
|
145
|
+
if (values.length === 0) {
|
|
146
|
+
throw new Error("http.origins must contain at least one origin");
|
|
147
|
+
}
|
|
148
|
+
config.http = { ...config.http, origins: values.map(parseOrigin) };
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
await writeConfig(config);
|
|
153
|
+
}
|
|
154
|
+
/** Removes one setting so its default applies, preserving its siblings. */
|
|
155
|
+
export async function unsetSetting(name) {
|
|
156
|
+
const config = await readConfig();
|
|
157
|
+
let changed = false;
|
|
158
|
+
if (name === "storage") {
|
|
159
|
+
changed = config.storage !== undefined;
|
|
160
|
+
delete config.storage;
|
|
161
|
+
}
|
|
162
|
+
else if (config.http !== undefined) {
|
|
163
|
+
const key = name.slice("http.".length);
|
|
164
|
+
changed = config.http[key] !== undefined;
|
|
165
|
+
delete config.http[key];
|
|
166
|
+
if (Object.keys(config.http).length === 0)
|
|
167
|
+
delete config.http;
|
|
168
|
+
}
|
|
169
|
+
if (changed)
|
|
170
|
+
await writeConfig(config);
|
|
171
|
+
}
|
|
172
|
+
/** Parses a CLI port value and rejects anything outside the TCP port range. */
|
|
173
|
+
export function parsePort(value) {
|
|
174
|
+
if (!/^\d+$/u.test(value)) {
|
|
175
|
+
throw new Error("http.port must be an integer from 1 to 65535");
|
|
176
|
+
}
|
|
177
|
+
const port = Number(value);
|
|
178
|
+
if (!isPort(port))
|
|
179
|
+
throw new Error("http.port must be an integer from 1 to 65535");
|
|
180
|
+
return port;
|
|
181
|
+
}
|
|
182
|
+
function resolveStorage(folder) {
|
|
183
|
+
if (folder === "~")
|
|
184
|
+
return homedir();
|
|
185
|
+
return folder.startsWith("~/") ? resolve(homedir(), folder.slice(2)) : resolve(folder);
|
|
186
|
+
}
|
|
187
|
+
function parseOrigin(value) {
|
|
188
|
+
const origin = normalizeHttpOrigin(value);
|
|
189
|
+
if (origin === undefined) {
|
|
190
|
+
throw new Error("http.origins must contain only http or https origins without paths");
|
|
191
|
+
}
|
|
192
|
+
return origin;
|
|
193
|
+
}
|
|
194
|
+
/** Returns the URL-normalized form of a strict HTTP origin, or undefined when invalid. */
|
|
195
|
+
export function normalizeHttpOrigin(value) {
|
|
196
|
+
const match = /^https?:\/\/(.+)$/iu.exec(value);
|
|
197
|
+
if (match === null)
|
|
198
|
+
return undefined;
|
|
199
|
+
const authority = match[1];
|
|
200
|
+
if (authority === undefined
|
|
201
|
+
|| authority.trim() !== authority
|
|
202
|
+
|| /[\s/\\?#@]/u.test(authority)) {
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
if (authority.startsWith("[")) {
|
|
206
|
+
const closingBracket = authority.indexOf("]");
|
|
207
|
+
if (closingBracket <= 1
|
|
208
|
+
|| (authority.slice(closingBracket + 1) !== ""
|
|
209
|
+
&& !/^:\d+$/u.test(authority.slice(closingBracket + 1)))) {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
const firstColon = authority.indexOf(":");
|
|
215
|
+
if (firstColon !== -1
|
|
216
|
+
&& (firstColon !== authority.lastIndexOf(":")
|
|
217
|
+
|| !/^\d+$/u.test(authority.slice(firstColon + 1)))) {
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const url = new URL(value);
|
|
223
|
+
if ((url.protocol !== "http:" && url.protocol !== "https:")
|
|
224
|
+
|| url.hostname === ""
|
|
225
|
+
|| url.username !== ""
|
|
226
|
+
|| url.password !== "") {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
return url.origin;
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function isPort(value) {
|
|
236
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 65_535;
|
|
237
|
+
}
|
|
238
|
+
function canonicalConfig(config) {
|
|
239
|
+
const host = config.http?.host;
|
|
240
|
+
const port = config.http?.port;
|
|
241
|
+
const origins = config.http?.origins;
|
|
242
|
+
return {
|
|
243
|
+
...(config.storage === undefined ? {} : { storage: config.storage }),
|
|
244
|
+
...(host === undefined && port === undefined && origins === undefined
|
|
245
|
+
? {}
|
|
246
|
+
: {
|
|
247
|
+
http: {
|
|
248
|
+
...(host === undefined ? {} : { host }),
|
|
249
|
+
...(port === undefined ? {} : { port }),
|
|
250
|
+
...(origins === undefined ? {} : { origins }),
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function isObject(value) {
|
|
256
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Mounts Autofile's transport-independent MCP server on Node's HTTP server. */
|
|
2
|
+
import { type HttpSettings } from "./config.js";
|
|
3
|
+
import type { Store } from "./store.js";
|
|
4
|
+
export interface RunningHttpServer {
|
|
5
|
+
endpoint: URL;
|
|
6
|
+
closed: Promise<void>;
|
|
7
|
+
close(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
/** Starts one modern-only Streamable HTTP endpoint around a process-shared store. */
|
|
10
|
+
export declare function startHttpServer(store: Store, dataFolder: string, settings: HttpSettings, onError: (error: Error) => void): Promise<RunningHttpServer>;
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** Mounts Autofile's transport-independent MCP server on Node's HTTP server. */
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
import { toNodeHandler } from "@modelcontextprotocol/node";
|
|
4
|
+
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
5
|
+
import { normalizeHttpOrigin } from "./config.js";
|
|
6
|
+
import { buildServer } from "./server.js";
|
|
7
|
+
import { resourceNotificationUris, watchStore } from "./watch.js";
|
|
8
|
+
const MAX_REQUEST_BODY_BYTES = 64 * 1024 * 1024;
|
|
9
|
+
const CORS_ALLOW_HEADERS = "Content-Type, MCP-Protocol-Version, Mcp-Method, Mcp-Name";
|
|
10
|
+
/** Starts one modern-only Streamable HTTP endpoint around a process-shared store. */
|
|
11
|
+
export async function startHttpServer(store, dataFolder, settings, onError) {
|
|
12
|
+
const handler = createMcpHandler(() => buildServer(store), {
|
|
13
|
+
legacy: "reject",
|
|
14
|
+
maxRequestBodySize: MAX_REQUEST_BODY_BYTES,
|
|
15
|
+
onerror: onError,
|
|
16
|
+
});
|
|
17
|
+
const watcher = await watchStore(dataFolder, store, (batch) => {
|
|
18
|
+
const uris = new Set(batch.changes.flatMap(({ uri }) => resourceNotificationUris(uri)));
|
|
19
|
+
for (const uri of uris) {
|
|
20
|
+
handler.notify.resourceUpdated(uri);
|
|
21
|
+
}
|
|
22
|
+
if (batch.listChanged)
|
|
23
|
+
handler.notify.resourcesChanged();
|
|
24
|
+
}, onError);
|
|
25
|
+
const serveMcp = toNodeHandler(handler, { maxRequestBodySize: MAX_REQUEST_BODY_BYTES });
|
|
26
|
+
const allowedOrigins = new Set(settings.origins);
|
|
27
|
+
const allowedHosts = new Set([
|
|
28
|
+
"localhost",
|
|
29
|
+
"127.0.0.1",
|
|
30
|
+
"[::1]",
|
|
31
|
+
...settings.origins.map((origin) => new URL(origin).hostname.toLowerCase()),
|
|
32
|
+
]);
|
|
33
|
+
const httpServer = createServer((request, response) => {
|
|
34
|
+
void routeRequest(request, response, allowedOrigins, allowedHosts, serveMcp);
|
|
35
|
+
});
|
|
36
|
+
const closed = new Promise((resolveClosed) => httpServer.once("close", resolveClosed));
|
|
37
|
+
try {
|
|
38
|
+
await new Promise((resolveListening, reject) => {
|
|
39
|
+
const onError = (error) => reject(error);
|
|
40
|
+
httpServer.once("error", onError);
|
|
41
|
+
httpServer.listen(settings.port, settings.host, () => {
|
|
42
|
+
httpServer.off("error", onError);
|
|
43
|
+
resolveListening();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
await Promise.all([watcher.close(), handler.close()]);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
const endpoint = new URL(`http://${urlHost(settings.host)}:${settings.port}/mcp`);
|
|
52
|
+
let closing;
|
|
53
|
+
return {
|
|
54
|
+
endpoint,
|
|
55
|
+
closed,
|
|
56
|
+
close() {
|
|
57
|
+
closing ??= closeHttpServer();
|
|
58
|
+
return closing;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
async function closeHttpServer() {
|
|
62
|
+
httpServer.close();
|
|
63
|
+
httpServer.closeAllConnections();
|
|
64
|
+
await Promise.all([watcher.close(), handler.close(), closed]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function routeRequest(request, response, allowedOrigins, allowedHosts, serveMcp) {
|
|
68
|
+
if (!isAllowedHost(request.headers.host, allowedHosts)) {
|
|
69
|
+
refuse(response, 403, "Forbidden\n");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const origin = request.headers.origin;
|
|
73
|
+
if (origin !== undefined && !isAllowedOrigin(origin, allowedOrigins)) {
|
|
74
|
+
refuse(response, 403, "Forbidden\n");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (requestPath(request) !== "/mcp") {
|
|
78
|
+
refuse(response, 404, "Not Found\n");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (origin !== undefined)
|
|
82
|
+
setCorsHeaders(response, origin);
|
|
83
|
+
if (request.method === "OPTIONS") {
|
|
84
|
+
response.setHeader("Connection", "close");
|
|
85
|
+
response.writeHead(204, {
|
|
86
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
87
|
+
"Access-Control-Allow-Headers": CORS_ALLOW_HEADERS,
|
|
88
|
+
}).end();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
await serveMcp(request, response);
|
|
92
|
+
}
|
|
93
|
+
function requestPath(request) {
|
|
94
|
+
try {
|
|
95
|
+
return new URL(request.url ?? "", "http://autofile.local").pathname;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function isAllowedOrigin(origin, allowedOrigins) {
|
|
102
|
+
const normalized = normalizeHttpOrigin(origin);
|
|
103
|
+
if (normalized === undefined)
|
|
104
|
+
return false;
|
|
105
|
+
const hostname = new URL(normalized).hostname.toLowerCase();
|
|
106
|
+
return hostname === "localhost"
|
|
107
|
+
|| hostname === "127.0.0.1"
|
|
108
|
+
|| hostname === "[::1]"
|
|
109
|
+
|| allowedOrigins.has(normalized);
|
|
110
|
+
}
|
|
111
|
+
function isAllowedHost(host, allowedHosts) {
|
|
112
|
+
const hostname = host === undefined ? undefined : hostHeaderName(host);
|
|
113
|
+
return hostname !== undefined && allowedHosts.has(hostname);
|
|
114
|
+
}
|
|
115
|
+
function hostHeaderName(host) {
|
|
116
|
+
if (host === "" || host.trim() !== host || /[\s/\\?#@,]/u.test(host))
|
|
117
|
+
return undefined;
|
|
118
|
+
if (host.startsWith("[")) {
|
|
119
|
+
const closingBracket = host.indexOf("]");
|
|
120
|
+
if (closingBracket <= 1
|
|
121
|
+
|| (host.slice(closingBracket + 1) !== ""
|
|
122
|
+
&& !/^:\d+$/u.test(host.slice(closingBracket + 1)))) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const firstColon = host.indexOf(":");
|
|
128
|
+
if (firstColon !== -1
|
|
129
|
+
&& (firstColon !== host.lastIndexOf(":")
|
|
130
|
+
|| !/^\d+$/u.test(host.slice(firstColon + 1)))) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
return new URL(`http://${host}`).hostname.toLowerCase();
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function refuse(response, status, body) {
|
|
142
|
+
response.setHeader("Connection", "close");
|
|
143
|
+
response.writeHead(status).end(body);
|
|
144
|
+
}
|
|
145
|
+
function setCorsHeaders(response, origin) {
|
|
146
|
+
response.setHeader("Access-Control-Allow-Origin", origin);
|
|
147
|
+
response.setHeader("Vary", "Origin");
|
|
148
|
+
}
|
|
149
|
+
function urlHost(host) {
|
|
150
|
+
return host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Shared compile-time types for the plain JSON crossing store boundaries. */
|
|
2
|
+
/** A scalar JSON value. */
|
|
3
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
4
|
+
/** Any value representable in JSON. */
|
|
5
|
+
export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
6
|
+
/** A JSON object with string keys. */
|
|
7
|
+
export interface JsonObject {
|
|
8
|
+
[key: string]: JsonValue;
|
|
9
|
+
}
|
package/dist/json.js
ADDED
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,8EAA8E"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers and checks Autofile's JSON Schemas with the explicitly selected
|
|
3
|
+
* 2020-12 dialect. The registry is process-global, so schemas are addressed by
|
|
4
|
+
* content and compiled once even when several store instances read them.
|
|
5
|
+
*/
|
|
6
|
+
import "@hyperjump/json-schema/formats";
|
|
7
|
+
import type { JsonObject, JsonValue } from "./json.js";
|
|
8
|
+
/** A compiled schema that returns all readable validation problems. */
|
|
9
|
+
export interface PreparedSchema {
|
|
10
|
+
validate(value: JsonValue): Promise<string[]>;
|
|
11
|
+
formatFields(value: JsonValue, format: "uri" | "blob"): FormatField[];
|
|
12
|
+
}
|
|
13
|
+
/** One instance value reached by a schema's `format` annotation. */
|
|
14
|
+
export interface FormatField {
|
|
15
|
+
pointer: string;
|
|
16
|
+
location: string;
|
|
17
|
+
value: JsonValue;
|
|
18
|
+
}
|
|
19
|
+
/** Checks that a declaration schema is safe, valid 2020-12 JSON Schema. */
|
|
20
|
+
export declare function prepareSchema(schema: JsonObject): Promise<PreparedSchema>;
|
|
21
|
+
/** A user-correctable problem in a proposed schema declaration. */
|
|
22
|
+
export declare class SchemaRefusal extends Error {
|
|
23
|
+
readonly messages: string[];
|
|
24
|
+
constructor(messages: string[]);
|
|
25
|
+
}
|