sashiko 0.11.4 → 0.13.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/README.md +74 -1
- package/dist/core/app/core.d.ts +23 -0
- package/dist/core/app/core.d.ts.map +1 -0
- package/dist/core/app/core.js +2 -0
- package/dist/core/app/core.js.map +1 -0
- package/dist/core/app/options.d.ts +109 -0
- package/dist/core/app/options.d.ts.map +1 -0
- package/dist/core/app/options.js +2 -0
- package/dist/core/app/options.js.map +1 -0
- package/dist/core/app.d.ts +34 -175
- package/dist/core/app.d.ts.map +1 -1
- package/dist/core/app.js +101 -496
- package/dist/core/app.js.map +1 -1
- package/dist/core/body-parser.d.ts +6 -3
- package/dist/core/body-parser.d.ts.map +1 -1
- package/dist/core/body-parser.js +8 -6
- package/dist/core/body-parser.js.map +1 -1
- package/dist/core/compiler.d.ts +2 -0
- package/dist/core/compiler.d.ts.map +1 -1
- package/dist/core/compiler.js.map +1 -1
- package/dist/core/compose.d.ts +7 -0
- package/dist/core/compose.d.ts.map +1 -1
- package/dist/core/compose.js +25 -0
- package/dist/core/compose.js.map +1 -1
- package/dist/core/context.d.ts +61 -14
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +162 -39
- package/dist/core/context.js.map +1 -1
- package/dist/core/health.js +1 -1
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/inject.d.ts.map +1 -1
- package/dist/core/inject.js +6 -0
- package/dist/core/inject.js.map +1 -1
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +41 -14
- package/dist/core/logger.js.map +1 -1
- package/dist/core/mounted-group.d.ts +5 -0
- package/dist/core/mounted-group.d.ts.map +1 -1
- package/dist/core/mounted-group.js +10 -0
- package/dist/core/mounted-group.js.map +1 -1
- package/dist/core/registry/framework-routes.d.ts +28 -0
- package/dist/core/registry/framework-routes.d.ts.map +1 -0
- package/dist/core/registry/framework-routes.js +83 -0
- package/dist/core/registry/framework-routes.js.map +1 -0
- package/dist/core/registry/registry.d.ts +53 -0
- package/dist/core/registry/registry.d.ts.map +1 -0
- package/dist/core/registry/registry.js +156 -0
- package/dist/core/registry/registry.js.map +1 -0
- package/dist/core/registry/route-program.d.ts +14 -0
- package/dist/core/registry/route-program.d.ts.map +1 -0
- package/dist/core/registry/route-program.js +29 -0
- package/dist/core/registry/route-program.js.map +1 -0
- package/dist/core/response/pipeline.d.ts +51 -0
- package/dist/core/response/pipeline.d.ts.map +1 -0
- package/dist/core/response/pipeline.js +171 -0
- package/dist/core/response/pipeline.js.map +1 -0
- package/dist/core/response.d.ts.map +1 -1
- package/dist/core/response.js +25 -0
- package/dist/core/response.js.map +1 -1
- package/dist/core/route-table.d.ts +5 -1
- package/dist/core/route-table.d.ts.map +1 -1
- package/dist/core/route-table.js +1 -1
- package/dist/core/route-table.js.map +1 -1
- package/dist/core/runtime/request-handler.d.ts +42 -0
- package/dist/core/runtime/request-handler.d.ts.map +1 -0
- package/dist/core/runtime/request-handler.js +187 -0
- package/dist/core/runtime/request-handler.js.map +1 -0
- package/dist/core/runtime/server.d.ts +41 -0
- package/dist/core/runtime/server.d.ts.map +1 -0
- package/dist/core/runtime/server.js +155 -0
- package/dist/core/runtime/server.js.map +1 -0
- package/dist/core/streaming/sse.d.ts +35 -0
- package/dist/core/streaming/sse.d.ts.map +1 -0
- package/dist/core/streaming/sse.js +121 -0
- package/dist/core/streaming/sse.js.map +1 -0
- package/dist/core/symbols.d.ts +14 -0
- package/dist/core/symbols.d.ts.map +1 -0
- package/dist/core/symbols.js +14 -0
- package/dist/core/symbols.js.map +1 -0
- package/dist/openapi/generate.d.ts.map +1 -1
- package/dist/openapi/generate.js +2 -0
- package/dist/openapi/generate.js.map +1 -1
- package/dist/server/static.d.ts +45 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +204 -0
- package/dist/server/static.js.map +1 -0
- package/dist/utils/content-type.d.ts.map +1 -1
- package/dist/utils/content-type.js +26 -6
- package/dist/utils/content-type.js.map +1 -1
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +52 -0
- package/dist/utils/mime.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/core/streaming/sse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,mHAAmH;AACnH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAC;IACrC,6EAA6E;IAC7E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0BAA0B;IAC1B,KAAK,IAAI,IAAI,CAAC;IACd,iGAAiG;IACjG,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,WAAW,UAAU;IACzB,wGAAwG;IACxG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoCD,+GAA+G;AAC/G,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,GAAG,SAAS,CAqE5F"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Campos de uma linha SSE não podem ter quebra de linha (seria injeção de evento); `id` também não pode
|
|
3
|
+
* ter U+0000, que faz o navegador ignorar o campo.
|
|
4
|
+
*/
|
|
5
|
+
const sseField = (name, value) => {
|
|
6
|
+
if (/[\r\n]/.test(value))
|
|
7
|
+
throw new Error(`[sashiko] ctx.sse(): "${name}" cannot contain line breaks.`);
|
|
8
|
+
if (name === 'id' && value.includes('\0'))
|
|
9
|
+
throw new Error('[sashiko] ctx.sse(): "id" cannot contain U+0000.');
|
|
10
|
+
return `${name}: ${value}\n`;
|
|
11
|
+
};
|
|
12
|
+
/** Maior intervalo dos timers do Node; acima disso, ele usa 1 ms (heartbeat contínuo). */
|
|
13
|
+
const MAX_TIMER_MS = 2_147_483_647;
|
|
14
|
+
/** `retry` e `heartbeatMs`: inteiro não negativo, como o protocolo exige, e dentro do limite dos timers. */
|
|
15
|
+
const nonNegativeInt = (name, value) => {
|
|
16
|
+
if (!Number.isInteger(value) || value < 0 || value > MAX_TIMER_MS) {
|
|
17
|
+
throw new Error(`[sashiko] ctx.sse(): "${name}" must be an integer between 0 and ${MAX_TIMER_MS} (got ${value}).`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
/** `data` do evento: strings como estão; o resto em JSON. Valor que não vira JSON gera erro claro, sem escrever nada. */
|
|
22
|
+
function sseData(data) {
|
|
23
|
+
if (typeof data === 'string')
|
|
24
|
+
return data;
|
|
25
|
+
let text;
|
|
26
|
+
try {
|
|
27
|
+
text = JSON.stringify(data);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw new Error(`[sashiko] ctx.sse(): "data" is not JSON-serializable (${err.message}).`, { cause: err });
|
|
31
|
+
}
|
|
32
|
+
if (text === undefined)
|
|
33
|
+
throw new Error(`[sashiko] ctx.sse(): "data" of type ${typeof data} is not JSON-serializable.`);
|
|
34
|
+
return text;
|
|
35
|
+
}
|
|
36
|
+
/** Abre a conexão SSE de `ctx`. `markStreaming` marca a resposta como stream (estado privado do `Context`). */
|
|
37
|
+
export function openSse(ctx, opts, markStreaming) {
|
|
38
|
+
if (ctx.sent)
|
|
39
|
+
throw new Error('[sashiko] ctx.sse(): the response was already sent.');
|
|
40
|
+
// Valida antes de abrir a resposta: um erro aqui ainda vira um 500 normal.
|
|
41
|
+
const heartbeatMs = nonNegativeInt('heartbeatMs', opts.heartbeatMs ?? 15_000);
|
|
42
|
+
if (opts.retry !== undefined)
|
|
43
|
+
nonNegativeInt('retry', opts.retry);
|
|
44
|
+
const res = ctx.res;
|
|
45
|
+
markStreaming();
|
|
46
|
+
res.statusCode = 200;
|
|
47
|
+
res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
|
|
48
|
+
res.setHeader('Cache-Control', 'no-cache, no-transform');
|
|
49
|
+
res.setHeader('X-Accel-Buffering', 'no');
|
|
50
|
+
res.removeHeader('Content-Length');
|
|
51
|
+
res.flushHeaders();
|
|
52
|
+
const listeners = [];
|
|
53
|
+
let closed = false;
|
|
54
|
+
const finish = () => {
|
|
55
|
+
if (closed)
|
|
56
|
+
return;
|
|
57
|
+
closed = true;
|
|
58
|
+
clearInterval(heartbeat);
|
|
59
|
+
for (const l of listeners.splice(0)) {
|
|
60
|
+
try {
|
|
61
|
+
l();
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
ctx.log.error({ err }, 'sse onClose listener failed');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const write = (chunk) => {
|
|
69
|
+
if (!closed && !res.writableEnded)
|
|
70
|
+
res.write(chunk);
|
|
71
|
+
};
|
|
72
|
+
const heartbeat = setInterval(() => write(': ping\n\n'), heartbeatMs || 2 ** 31 - 1);
|
|
73
|
+
heartbeat.unref();
|
|
74
|
+
if (!heartbeatMs)
|
|
75
|
+
clearInterval(heartbeat);
|
|
76
|
+
res.once('close', finish);
|
|
77
|
+
const signal = ctx.signal;
|
|
78
|
+
signal.addEventListener('abort', () => stream.close(), { once: true });
|
|
79
|
+
if (opts.retry !== undefined)
|
|
80
|
+
write(`retry: ${opts.retry}\n\n`);
|
|
81
|
+
const stream = {
|
|
82
|
+
send: (event) => {
|
|
83
|
+
const e = typeof event === 'string' ? { data: event } : event;
|
|
84
|
+
let out = '';
|
|
85
|
+
if (e.event !== undefined)
|
|
86
|
+
out += sseField('event', e.event);
|
|
87
|
+
if (e.id !== undefined)
|
|
88
|
+
out += sseField('id', e.id);
|
|
89
|
+
if (e.retry !== undefined)
|
|
90
|
+
out += `retry: ${nonNegativeInt('retry', e.retry)}\n`;
|
|
91
|
+
if (e.data === undefined)
|
|
92
|
+
throw new Error('[sashiko] ctx.sse(): "data" is required; use "" for an empty event.');
|
|
93
|
+
const text = sseData(e.data);
|
|
94
|
+
for (const line of text.split(/\r\n|\r|\n/))
|
|
95
|
+
out += `data: ${line}\n`;
|
|
96
|
+
write(`${out}\n`);
|
|
97
|
+
},
|
|
98
|
+
comment: (text) => write(`: ${text.replace(/[\r\n]+/g, ' ')}\n\n`),
|
|
99
|
+
close: () => {
|
|
100
|
+
if (!res.writableEnded)
|
|
101
|
+
res.end();
|
|
102
|
+
finish();
|
|
103
|
+
},
|
|
104
|
+
onClose: (listener) => {
|
|
105
|
+
if (closed)
|
|
106
|
+
listener();
|
|
107
|
+
else
|
|
108
|
+
listeners.push(listener);
|
|
109
|
+
},
|
|
110
|
+
get closed() {
|
|
111
|
+
return closed;
|
|
112
|
+
},
|
|
113
|
+
lastEventId: ctx.get('last-event-id'),
|
|
114
|
+
};
|
|
115
|
+
// O cliente pode ter desconectado antes do `ctx.sse()` (num `await` anterior): o 'close' e o 'abort' já
|
|
116
|
+
// passaram, e os listeners acima nunca rodariam. Encerra já, limpando o heartbeat e chamando `onClose`.
|
|
117
|
+
if (signal.aborted)
|
|
118
|
+
stream.close();
|
|
119
|
+
return stream;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=sse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../src/core/streaming/sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Símbolos internos do core. Ficam num módulo próprio para quem os usa não depender do `Context` em tempo de execução. */
|
|
2
|
+
/** @internal Envio cru, sem pipeline: usado pelo próprio pipeline, por erros e por 404/405. */
|
|
3
|
+
export declare const kRawSend: unique symbol;
|
|
4
|
+
/** @internal Cancela o `ctx.signal` (encerramento do app) (F-13). */
|
|
5
|
+
export declare const kAbort: unique symbol;
|
|
6
|
+
/** @internal Envio de arquivo em andamento, que o app aguarda mesmo sem `await` no handler (F-13). */
|
|
7
|
+
export declare const kPendingSend: unique symbol;
|
|
8
|
+
/** @internal Liga o contexto aos schemas de resposta da rota, antes do handler (F-32). */
|
|
9
|
+
export declare const kBindResponse: unique symbol;
|
|
10
|
+
/** @internal A cadeia global chegou ao roteamento (o último middleware chamou `next()`). */
|
|
11
|
+
export declare const kRouted: unique symbol;
|
|
12
|
+
/** @internal O `Context` de uma resposta em andamento, guardado na própria `ServerResponse` (F-39). */
|
|
13
|
+
export declare const kContext: unique symbol;
|
|
14
|
+
//# sourceMappingURL=symbols.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/core/symbols.ts"],"names":[],"mappings":"AAAA,2HAA2H;AAE3H,+FAA+F;AAC/F,eAAO,MAAM,QAAQ,eAA4B,CAAC;AAClD,qEAAqE;AACrE,eAAO,MAAM,MAAM,eAA0B,CAAC;AAC9C,sGAAsG;AACtG,eAAO,MAAM,YAAY,eAAgC,CAAC;AAC1D,0FAA0F;AAC1F,eAAO,MAAM,aAAa,eAAiC,CAAC;AAC5D,4FAA4F;AAC5F,eAAO,MAAM,OAAO,eAA2B,CAAC;AAChD,uGAAuG;AACvG,eAAO,MAAM,QAAQ,eAA4B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Símbolos internos do core. Ficam num módulo próprio para quem os usa não depender do `Context` em tempo de execução. */
|
|
2
|
+
/** @internal Envio cru, sem pipeline: usado pelo próprio pipeline, por erros e por 404/405. */
|
|
3
|
+
export const kRawSend = Symbol('sashiko.rawSend');
|
|
4
|
+
/** @internal Cancela o `ctx.signal` (encerramento do app) (F-13). */
|
|
5
|
+
export const kAbort = Symbol('sashiko.abort');
|
|
6
|
+
/** @internal Envio de arquivo em andamento, que o app aguarda mesmo sem `await` no handler (F-13). */
|
|
7
|
+
export const kPendingSend = Symbol('sashiko.pendingSend');
|
|
8
|
+
/** @internal Liga o contexto aos schemas de resposta da rota, antes do handler (F-32). */
|
|
9
|
+
export const kBindResponse = Symbol('sashiko.bindResponse');
|
|
10
|
+
/** @internal A cadeia global chegou ao roteamento (o último middleware chamou `next()`). */
|
|
11
|
+
export const kRouted = Symbol('sashiko.routed');
|
|
12
|
+
/** @internal O `Context` de uma resposta em andamento, guardado na própria `ServerResponse` (F-39). */
|
|
13
|
+
export const kContext = Symbol('sashiko.context');
|
|
14
|
+
//# sourceMappingURL=symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/core/symbols.ts"],"names":[],"mappings":"AAAA,2HAA2H;AAE3H,+FAA+F;AAC/F,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAClD,qEAAqE;AACrE,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAC9C,sGAAsG;AACtG,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAC1D,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAC5D,4FAA4F;AAC5F,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAChD,uGAAuG;AACvG,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/openapi/generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACxF,OAAO,CAAC,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,oFAAoF;IACpF,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACpC,2FAA2F;IAC3F,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;CAC3B;AAED,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAKpC,sHAAsH;AACtH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUlD;AA2DD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/openapi/generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACxF,OAAO,CAAC,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,oFAAoF;IACpF,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACpC,2FAA2F;IAC3F,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;CAC3B;AAED,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAKpC,sHAAsH;AACtH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUlD;AA2DD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI,CAqBpH;AASD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA2BrG"}
|
package/dist/openapi/generate.js
CHANGED
|
@@ -74,6 +74,8 @@ export function generateOpenAPI(routes, opts, problemErrors) {
|
|
|
74
74
|
const paths = {};
|
|
75
75
|
const ids = new Map();
|
|
76
76
|
for (const route of routes) {
|
|
77
|
+
if (route.internal)
|
|
78
|
+
continue;
|
|
77
79
|
const path = toOpenAPIPath(route.path);
|
|
78
80
|
const op = operation(route, problemErrors);
|
|
79
81
|
// A mesma classe montada em dois prefixos gera o mesmo id; o OpenAPI exige ids únicos.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/openapi/generate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/openapi/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type Stats } from 'node:fs';
|
|
2
|
+
import type { Context } from '../core/context.ts';
|
|
3
|
+
/** Opções comuns a `app.static()` e `ctx.sendFile()` (F-13). */
|
|
4
|
+
export interface FileOptions {
|
|
5
|
+
/** `Cache-Control: max-age`, em segundos ou como `'7d'`, `'12h'`, `'30m'`, `'10s'`. Padrão: 0 (revalida sempre). */
|
|
6
|
+
maxAge?: number | string;
|
|
7
|
+
/** Acrescenta `immutable` ao `Cache-Control`, para arquivos com hash no nome. */
|
|
8
|
+
immutable?: boolean;
|
|
9
|
+
/** `ETag` fraco (tamanho + data de modificação), com 304 para `If-None-Match`. Padrão: `true`. */
|
|
10
|
+
etag?: boolean;
|
|
11
|
+
/** `Last-Modified`, com 304 para `If-Modified-Since`. Padrão: `true`. */
|
|
12
|
+
lastModified?: boolean;
|
|
13
|
+
/** Tipos por extensão, somados à tabela interna: `{ glb: 'model/gltf-binary' }`. */
|
|
14
|
+
mimeTypes?: Readonly<Record<string, string>>;
|
|
15
|
+
}
|
|
16
|
+
export interface StaticOptions extends FileOptions {
|
|
17
|
+
/** Arquivo servido para um diretório. Padrão: `'index.html'`; `false` desliga. Diretórios nunca são listados. */
|
|
18
|
+
index?: string | false;
|
|
19
|
+
/**
|
|
20
|
+
* SPA: arquivo (relativo à raiz) servido quando o path pedido não existe **e não tem extensão**
|
|
21
|
+
* (`/pedidos/42` → `index.html`, mas `/app.js` inexistente continua 404). Sai com `no-cache`.
|
|
22
|
+
*/
|
|
23
|
+
fallback?: string;
|
|
24
|
+
/** Arquivos e pastas que começam com `.` (`.env`, `.git`): `'deny'` responde 404 (padrão) ou `'allow'`. */
|
|
25
|
+
dotfiles?: 'deny' | 'allow';
|
|
26
|
+
}
|
|
27
|
+
export interface SendFileOptions extends FileOptions {
|
|
28
|
+
/** Raiz que contém o arquivo; com ela, o path é relativo e não pode sair dela. Sem `root`, o path precisa ser absoluto. */
|
|
29
|
+
root?: string;
|
|
30
|
+
/** `Content-Disposition: attachment`. `true` usa o nome do arquivo; uma string define o nome do download. */
|
|
31
|
+
download?: boolean | string;
|
|
32
|
+
}
|
|
33
|
+
export declare function parseMaxAge(value: number | string | undefined): number;
|
|
34
|
+
/** Raiz real (symlinks resolvidos), conferida na configuração: um diretório que não existe falha cedo. */
|
|
35
|
+
export declare function resolveRoot(root: string): string;
|
|
36
|
+
/** Envia um arquivo já resolvido e conferido, com cache condicional e `Range` (F-13). */
|
|
37
|
+
export declare function sendResolvedFile(ctx: Context, path: string, s: Stats, opts: FileOptions & {
|
|
38
|
+
download?: boolean | string;
|
|
39
|
+
noCache?: boolean;
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
/** `ctx.sendFile()`: confere o caminho e envia (F-13). */
|
|
42
|
+
export declare function sendFile(ctx: Context, path: string, opts?: SendFileOptions): Promise<void>;
|
|
43
|
+
/** Handler de `app.static()`: resolve o resto do path dentro da raiz, com índice e fallback de SPA. */
|
|
44
|
+
export declare function staticHandler(rootInput: string, opts: StaticOptions): (ctx: Context) => Promise<void>;
|
|
45
|
+
//# sourceMappingURL=static.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,KAAK,EAAY,MAAM,SAAS,CAAC;AAG/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAKlD,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,oHAAoH;IACpH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kGAAkG;IAClG,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oFAAoF;IACpF,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,iHAAiH;IACjH,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2GAA2G;IAC3G,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,2HAA2H;IAC3H,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC7B;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAStE;AAED,0GAA0G;AAC1G,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAShD;AAgED,yFAAyF;AACzF,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,KAAK,EACR,IAAI,EAAE,WAAW,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACrE,OAAO,CAAC,IAAI,CAAC,CA0Df;AAED,0DAA0D;AAC1D,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAapG;AAED,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAwBrG"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { createReadStream, realpathSync, statSync } from 'node:fs';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, resolve, sep } from 'node:path';
|
|
4
|
+
import { kRawSend } from '../core/symbols.js';
|
|
5
|
+
import { HttpError } from '../core/errors.js';
|
|
6
|
+
import { contentTypeFor } from '../utils/mime.js';
|
|
7
|
+
const UNITS = { s: 1, m: 60, h: 3600, d: 86_400 };
|
|
8
|
+
export function parseMaxAge(value) {
|
|
9
|
+
if (value === undefined)
|
|
10
|
+
return 0;
|
|
11
|
+
if (typeof value === 'number') {
|
|
12
|
+
if (!Number.isFinite(value) || value < 0)
|
|
13
|
+
throw new Error(`[sashiko] invalid maxAge ${value}.`);
|
|
14
|
+
return Math.floor(value);
|
|
15
|
+
}
|
|
16
|
+
const m = /^(\d+)\s*([smhd])$/.exec(value.trim());
|
|
17
|
+
if (!m)
|
|
18
|
+
throw new Error(`[sashiko] invalid maxAge "${value}"; use seconds or "10s", "30m", "12h", "7d".`);
|
|
19
|
+
return Number(m[1]) * UNITS[m[2]];
|
|
20
|
+
}
|
|
21
|
+
/** Raiz real (symlinks resolvidos), conferida na configuração: um diretório que não existe falha cedo. */
|
|
22
|
+
export function resolveRoot(root) {
|
|
23
|
+
let real;
|
|
24
|
+
try {
|
|
25
|
+
real = realpathSync(resolve(root));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`[sashiko] static root "${root}" does not exist.`);
|
|
29
|
+
}
|
|
30
|
+
if (!statSync(real).isDirectory())
|
|
31
|
+
throw new Error(`[sashiko] static root "${root}" is not a directory.`);
|
|
32
|
+
return real;
|
|
33
|
+
}
|
|
34
|
+
const notFound = () => new HttpError(404, 'Not Found', 'NOT_FOUND');
|
|
35
|
+
/**
|
|
36
|
+
* Caminho dentro da raiz, ou `undefined` se a requisição tentar sair dela (path traversal) (F-13):
|
|
37
|
+
* byte nulo, barra invertida e segmentos `..` são recusados antes de resolver, e o resultado real
|
|
38
|
+
* (depois de seguir symlinks) precisa continuar dentro da raiz.
|
|
39
|
+
*/
|
|
40
|
+
async function insideRoot(root, relative, dotfiles) {
|
|
41
|
+
if (relative.includes('\0') || relative.includes('\\'))
|
|
42
|
+
return undefined;
|
|
43
|
+
const segments = relative.split('/').filter((s) => s !== '' && s !== '.');
|
|
44
|
+
if (segments.some((s) => s === '..'))
|
|
45
|
+
return undefined;
|
|
46
|
+
if (dotfiles === 'deny' && segments.some((s) => s.startsWith('.')))
|
|
47
|
+
return undefined;
|
|
48
|
+
const candidate = resolve(root, ...segments);
|
|
49
|
+
if (candidate !== root && !candidate.startsWith(root + sep))
|
|
50
|
+
return undefined;
|
|
51
|
+
try {
|
|
52
|
+
const real = await realpath(candidate);
|
|
53
|
+
return real === root || real.startsWith(root + sep) ? real : undefined;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return candidate; // não existe: o stat responde 404 adiante
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function fileStat(path) {
|
|
60
|
+
try {
|
|
61
|
+
return await stat(path);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const etagOf = (s) => `W/"${s.size.toString(16)}-${Math.floor(s.mtimeMs).toString(16)}"`;
|
|
68
|
+
function contentDisposition(name) {
|
|
69
|
+
const ascii = name.replace(/[^\x20-\x7e]/g, '_').replace(/["\\]/g, '_');
|
|
70
|
+
return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(name)}`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* `bytes=a-b`, `bytes=a-` ou `bytes=-n` sobre `size`. `undefined` = não satisfazível (416); `null` = ignorar
|
|
74
|
+
* e enviar o arquivo inteiro (outra unidade, vários intervalos ou sintaxe que não entendemos, RFC 9110 §14.2).
|
|
75
|
+
*/
|
|
76
|
+
function parseRange(header, size) {
|
|
77
|
+
const value = header.trim();
|
|
78
|
+
if (!/^bytes=/i.test(value) || value.includes(','))
|
|
79
|
+
return null;
|
|
80
|
+
const m = /^bytes=(\d*)-(\d*)$/i.exec(value);
|
|
81
|
+
if (!m)
|
|
82
|
+
return null;
|
|
83
|
+
const [, a, b] = m;
|
|
84
|
+
if (a === '' && b === '')
|
|
85
|
+
return undefined;
|
|
86
|
+
let start;
|
|
87
|
+
let end;
|
|
88
|
+
if (a === '') {
|
|
89
|
+
const n = Number(b);
|
|
90
|
+
if (n === 0)
|
|
91
|
+
return undefined;
|
|
92
|
+
start = Math.max(0, size - n);
|
|
93
|
+
end = size - 1;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
start = Number(a);
|
|
97
|
+
end = b === '' ? size - 1 : Math.min(Number(b), size - 1);
|
|
98
|
+
}
|
|
99
|
+
return start > end || start >= size ? undefined : { start, end };
|
|
100
|
+
}
|
|
101
|
+
/** Envia um arquivo já resolvido e conferido, com cache condicional e `Range` (F-13). */
|
|
102
|
+
export async function sendResolvedFile(ctx, path, s, opts) {
|
|
103
|
+
const res = ctx.res;
|
|
104
|
+
const type = contentTypeFor(path, opts.mimeTypes);
|
|
105
|
+
const etag = opts.etag === false ? undefined : etagOf(s);
|
|
106
|
+
const modified = opts.lastModified === false ? undefined : new Date(Math.floor(s.mtimeMs / 1000) * 1000);
|
|
107
|
+
if (etag)
|
|
108
|
+
res.setHeader('ETag', etag);
|
|
109
|
+
if (modified)
|
|
110
|
+
res.setHeader('Last-Modified', modified.toUTCString());
|
|
111
|
+
const maxAge = parseMaxAge(opts.maxAge);
|
|
112
|
+
res.setHeader('Cache-Control', opts.noCache ? 'no-cache' : `public, max-age=${maxAge}${opts.immutable ? ', immutable' : ''}`);
|
|
113
|
+
res.setHeader('Accept-Ranges', 'bytes');
|
|
114
|
+
if (opts.download) {
|
|
115
|
+
const name = typeof opts.download === 'string' ? opts.download : (path.split(sep).pop() ?? 'download');
|
|
116
|
+
res.setHeader('Content-Disposition', contentDisposition(name));
|
|
117
|
+
}
|
|
118
|
+
// Condicionais (RFC 9110): If-None-Match prevalece sobre If-Modified-Since.
|
|
119
|
+
const inm = ctx.get('if-none-match');
|
|
120
|
+
const ims = ctx.get('if-modified-since');
|
|
121
|
+
const fresh = inm
|
|
122
|
+
? etag !== undefined && inm.split(',').some((t) => t.trim() === '*' || t.trim().replace(/^W\//, '') === etag.replace(/^W\//, ''))
|
|
123
|
+
: ims !== undefined && modified !== undefined && !Number.isNaN(Date.parse(ims)) && modified.getTime() <= Date.parse(ims);
|
|
124
|
+
if (fresh) {
|
|
125
|
+
res.statusCode = 304;
|
|
126
|
+
res.removeHeader('Content-Type');
|
|
127
|
+
return void res.end();
|
|
128
|
+
}
|
|
129
|
+
let start = 0;
|
|
130
|
+
let end = s.size - 1;
|
|
131
|
+
const rangeHeader = ctx.get('range');
|
|
132
|
+
const ifRange = ctx.get('if-range');
|
|
133
|
+
// Range só vale para GET. If-Range exige comparação forte: nossos ETags são fracos e nunca a satisfazem;
|
|
134
|
+
// uma data precisa ser exatamente o Last-Modified (RFC 9110 §13.1.5).
|
|
135
|
+
const ifRangeOk = !ifRange ||
|
|
136
|
+
(!ifRange.startsWith('"') && !ifRange.startsWith('W/') && modified !== undefined && Date.parse(ifRange) === modified.getTime());
|
|
137
|
+
const rangeApplies = ctx.method === 'GET' && rangeHeader !== undefined && ifRangeOk;
|
|
138
|
+
if (rangeApplies && s.size > 0) {
|
|
139
|
+
const range = parseRange(rangeHeader, s.size);
|
|
140
|
+
if (range === undefined) {
|
|
141
|
+
res.statusCode = 416;
|
|
142
|
+
res.setHeader('Content-Range', `bytes */${s.size}`);
|
|
143
|
+
return void res.end();
|
|
144
|
+
}
|
|
145
|
+
if (range) {
|
|
146
|
+
({ start, end } = range);
|
|
147
|
+
res.statusCode = 206;
|
|
148
|
+
res.setHeader('Content-Range', `bytes ${start}-${end}/${s.size}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
res.setHeader('Content-Length', String(s.size === 0 ? 0 : end - start + 1));
|
|
152
|
+
if (ctx.method === 'HEAD' || s.size === 0) {
|
|
153
|
+
res.setHeader('Content-Type', type);
|
|
154
|
+
return void res.end();
|
|
155
|
+
}
|
|
156
|
+
ctx[kRawSend](createReadStream(path, { start, end }), type);
|
|
157
|
+
}
|
|
158
|
+
/** `ctx.sendFile()`: confere o caminho e envia (F-13). */
|
|
159
|
+
export async function sendFile(ctx, path, opts = {}) {
|
|
160
|
+
// Como `ctx.json()`/`ctx.send()`: depois que a resposta saiu, um novo envio é ignorado (sem mexer nos headers).
|
|
161
|
+
if (ctx.sent)
|
|
162
|
+
return;
|
|
163
|
+
let full;
|
|
164
|
+
if (opts.root !== undefined) {
|
|
165
|
+
full = await insideRoot(resolveRoot(opts.root), path, 'deny');
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
if (!isAbsolute(path))
|
|
169
|
+
throw new Error('[sashiko] ctx.sendFile(): use an absolute path, or pass { root } with a relative one.');
|
|
170
|
+
full = path;
|
|
171
|
+
}
|
|
172
|
+
const s = full ? await fileStat(full) : undefined;
|
|
173
|
+
if (!full || !s?.isFile())
|
|
174
|
+
throw notFound();
|
|
175
|
+
await sendResolvedFile(ctx, full, s, opts);
|
|
176
|
+
}
|
|
177
|
+
/** Handler de `app.static()`: resolve o resto do path dentro da raiz, com índice e fallback de SPA. */
|
|
178
|
+
export function staticHandler(rootInput, opts) {
|
|
179
|
+
const root = resolveRoot(rootInput);
|
|
180
|
+
parseMaxAge(opts.maxAge); // valida já
|
|
181
|
+
const dotfiles = opts.dotfiles ?? 'deny';
|
|
182
|
+
const index = opts.index === undefined ? 'index.html' : opts.index;
|
|
183
|
+
return async (ctx) => {
|
|
184
|
+
const rest = ctx.params['*'] ?? '';
|
|
185
|
+
let full = await insideRoot(root, rest, dotfiles);
|
|
186
|
+
let s = full ? await fileStat(full) : undefined;
|
|
187
|
+
if (full && s?.isDirectory()) {
|
|
188
|
+
full = index ? await insideRoot(root, `${rest}/${index}`, dotfiles) : undefined;
|
|
189
|
+
s = full ? await fileStat(full) : undefined;
|
|
190
|
+
}
|
|
191
|
+
if (full && s?.isFile())
|
|
192
|
+
return sendResolvedFile(ctx, full, s, opts);
|
|
193
|
+
// SPA: só para paths sem extensão, para um asset que falta continuar 404.
|
|
194
|
+
const last = rest.split('/').pop() ?? '';
|
|
195
|
+
if (opts.fallback && full !== undefined && !last.includes('.')) {
|
|
196
|
+
const fb = await insideRoot(root, opts.fallback, 'allow');
|
|
197
|
+
const fs = fb ? await fileStat(fb) : undefined;
|
|
198
|
+
if (fb && fs?.isFile())
|
|
199
|
+
return sendResolvedFile(ctx, fb, fs, { ...opts, noCache: true });
|
|
200
|
+
}
|
|
201
|
+
throw notFound();
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAU5D;AAGD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAsBtG;AAYD,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYhD;AAGD,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGrE"}
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/** Media type sem parâmetros e em minúsculas: `"Application/JSON; charset=utf-8"` → `"application/json"`. */
|
|
2
2
|
export function mediaType(header) {
|
|
3
|
-
|
|
3
|
+
if (!header)
|
|
4
|
+
return '';
|
|
5
|
+
let base = MEDIA_TYPES.get(header);
|
|
6
|
+
if (base === undefined) {
|
|
7
|
+
base = header.split(';', 1)[0].trim().toLowerCase();
|
|
8
|
+
// Memoizado com limite: os tipos vêm da configuração e dos handlers (baixa cardinalidade), mas um
|
|
9
|
+
// Content-Type montado com dado do cliente não pode fazer o mapa crescer sem fim.
|
|
10
|
+
if (MEDIA_TYPES.size < 256)
|
|
11
|
+
MEDIA_TYPES.set(header, base);
|
|
12
|
+
}
|
|
13
|
+
return base;
|
|
4
14
|
}
|
|
15
|
+
const MEDIA_TYPES = new Map();
|
|
5
16
|
/**
|
|
6
17
|
* Escolhe, entre os tipos `available` (em ordem de preferência do servidor), o melhor para o
|
|
7
18
|
* header `Accept` (F-31). Respeita q-values e curingas (`text/*`, `*\/*`). Sem `Accept`,
|
|
@@ -41,12 +52,21 @@ function matches(range, type) {
|
|
|
41
52
|
}
|
|
42
53
|
/** Acrescenta `charset=utf-8` a tipos textuais sem charset. */
|
|
43
54
|
export function withCharset(type) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
let out = WITH_CHARSET.get(type);
|
|
56
|
+
if (out === undefined) {
|
|
57
|
+
if (/;\s*charset=/i.test(type))
|
|
58
|
+
out = type;
|
|
59
|
+
else {
|
|
60
|
+
const base = mediaType(type);
|
|
61
|
+
const textual = base.startsWith('text/') || isJsonContentType(base) || /\+xml$|\/xml$|yaml$/.test(base);
|
|
62
|
+
out = textual ? `${type}; charset=utf-8` : type;
|
|
63
|
+
}
|
|
64
|
+
if (WITH_CHARSET.size < 256)
|
|
65
|
+
WITH_CHARSET.set(type, out);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
49
68
|
}
|
|
69
|
+
const WITH_CHARSET = new Map();
|
|
50
70
|
/** `application/json` ou `application/*+json`, com parâmetros opcionais (B-11). */
|
|
51
71
|
export function isJsonContentType(header) {
|
|
52
72
|
const type = mediaType(header);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.js","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,UAAU,SAAS,CAAC,MAA0B;IAClD,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"content-type.js","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mime.d.ts","sourceRoot":"","sources":["../../src/utils/mime.ts"],"names":[],"mappings":"AA+CA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAAG,MAAM,CAKrG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos de conteúdo por extensão, sem dependência (F-13). Cobre o que uma API e uma SPA servem; o resto
|
|
3
|
+
* sai como `application/octet-stream` (com `nosniff`, o navegador não tenta adivinhar). Acrescente tipos
|
|
4
|
+
* com a opção `mimeTypes` do `static()`/`sendFile()`.
|
|
5
|
+
*/
|
|
6
|
+
const TYPES = {
|
|
7
|
+
html: 'text/html',
|
|
8
|
+
htm: 'text/html',
|
|
9
|
+
css: 'text/css',
|
|
10
|
+
js: 'text/javascript',
|
|
11
|
+
mjs: 'text/javascript',
|
|
12
|
+
cjs: 'text/javascript',
|
|
13
|
+
json: 'application/json',
|
|
14
|
+
map: 'application/json',
|
|
15
|
+
webmanifest: 'application/manifest+json',
|
|
16
|
+
txt: 'text/plain',
|
|
17
|
+
md: 'text/markdown',
|
|
18
|
+
csv: 'text/csv',
|
|
19
|
+
xml: 'application/xml',
|
|
20
|
+
yaml: 'application/yaml',
|
|
21
|
+
yml: 'application/yaml',
|
|
22
|
+
svg: 'image/svg+xml',
|
|
23
|
+
png: 'image/png',
|
|
24
|
+
jpg: 'image/jpeg',
|
|
25
|
+
jpeg: 'image/jpeg',
|
|
26
|
+
gif: 'image/gif',
|
|
27
|
+
webp: 'image/webp',
|
|
28
|
+
avif: 'image/avif',
|
|
29
|
+
ico: 'image/x-icon',
|
|
30
|
+
woff: 'font/woff',
|
|
31
|
+
woff2: 'font/woff2',
|
|
32
|
+
ttf: 'font/ttf',
|
|
33
|
+
otf: 'font/otf',
|
|
34
|
+
pdf: 'application/pdf',
|
|
35
|
+
zip: 'application/zip',
|
|
36
|
+
gz: 'application/gzip',
|
|
37
|
+
wasm: 'application/wasm',
|
|
38
|
+
mp4: 'video/mp4',
|
|
39
|
+
webm: 'video/webm',
|
|
40
|
+
mp3: 'audio/mpeg',
|
|
41
|
+
wav: 'audio/wav',
|
|
42
|
+
ogg: 'audio/ogg',
|
|
43
|
+
};
|
|
44
|
+
/** Tipos de texto recebem `charset=utf-8`. */
|
|
45
|
+
const TEXT = /^(text\/|application\/(json|manifest\+json|xml|yaml|javascript))|\+xml$|\+json$/;
|
|
46
|
+
export function contentTypeFor(filename, extra = {}) {
|
|
47
|
+
const dot = filename.lastIndexOf('.');
|
|
48
|
+
const ext = dot === -1 ? '' : filename.slice(dot + 1).toLowerCase();
|
|
49
|
+
const type = extra[ext] ?? TYPES[ext] ?? 'application/octet-stream';
|
|
50
|
+
return TEXT.test(type) && !type.includes('charset') ? `${type}; charset=utf-8` : type;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=mime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../../src/utils/mime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,KAAK,GAA2B;IACpC,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,UAAU;IACf,EAAE,EAAE,iBAAiB;IACrB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,kBAAkB;IACvB,WAAW,EAAE,2BAA2B;IACxC,GAAG,EAAE,YAAY;IACjB,EAAE,EAAE,eAAe;IACnB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,cAAc;IACnB,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,YAAY;IACnB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,iBAAiB;IACtB,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;CACjB,CAAC;AAEF,8CAA8C;AAC9C,MAAM,IAAI,GAAG,iFAAiF,CAAC;AAE/F,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,KAAK,GAAqC,EAAE;IAC3F,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC;IACpE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;AACxF,CAAC"}
|