@holo-js/kernel 0.3.27 → 0.3.28
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/dist/file-content.d.ts +9 -0
- package/dist/file-content.mjs +54 -0
- package/dist/image-decoding.browser.d.ts +3 -0
- package/dist/image-decoding.browser.mjs +7 -0
- package/dist/image-decoding.d.ts +3 -0
- package/dist/image-decoding.mjs +7 -0
- package/dist/image-decoding.node.d.ts +3 -0
- package/dist/image-decoding.node.mjs +70 -0
- package/dist/index.d.ts +34 -1
- package/dist/index.mjs +132 -1
- package/package.json +26 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type FileContentInspection = {
|
|
2
|
+
readonly mimeType: string | null;
|
|
3
|
+
readonly passive: boolean;
|
|
4
|
+
};
|
|
5
|
+
declare const fileContentSampleBytes = 65536;
|
|
6
|
+
declare function mimeTypeFromFileName(fileName: string): string | null;
|
|
7
|
+
declare function inspectFileContent(sample: Uint8Array, fileName?: string): Promise<FileContentInspection>;
|
|
8
|
+
|
|
9
|
+
export { type FileContentInspection, fileContentSampleBytes, inspectFileContent, mimeTypeFromFileName };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/fileContent.ts
|
|
2
|
+
var fileContentSampleBytes = 65536;
|
|
3
|
+
var mimeTypesByExtension = Object.freeze({
|
|
4
|
+
avif: "image/avif",
|
|
5
|
+
css: "text/css",
|
|
6
|
+
csv: "text/csv",
|
|
7
|
+
gif: "image/gif",
|
|
8
|
+
htm: "text/html",
|
|
9
|
+
html: "text/html",
|
|
10
|
+
jpeg: "image/jpeg",
|
|
11
|
+
jpg: "image/jpeg",
|
|
12
|
+
json: "application/json",
|
|
13
|
+
md: "text/markdown",
|
|
14
|
+
mp3: "audio/mpeg",
|
|
15
|
+
pdf: "application/pdf",
|
|
16
|
+
png: "image/png",
|
|
17
|
+
svg: "image/svg+xml",
|
|
18
|
+
txt: "text/plain",
|
|
19
|
+
webp: "image/webp",
|
|
20
|
+
woff: "font/woff",
|
|
21
|
+
woff2: "font/woff2",
|
|
22
|
+
xml: "application/xml"
|
|
23
|
+
});
|
|
24
|
+
var passiveDocumentMimeTypes = /* @__PURE__ */ new Set([
|
|
25
|
+
"application/json",
|
|
26
|
+
"application/pdf",
|
|
27
|
+
"text/css",
|
|
28
|
+
"text/csv",
|
|
29
|
+
"text/markdown",
|
|
30
|
+
"text/plain"
|
|
31
|
+
]);
|
|
32
|
+
function isPassiveMimeType(mimeType) {
|
|
33
|
+
if (!mimeType) return false;
|
|
34
|
+
return passiveDocumentMimeTypes.has(mimeType) || /^(?:image|audio|video|font)\//u.test(mimeType) && !mimeType.endsWith("+xml");
|
|
35
|
+
}
|
|
36
|
+
function mimeTypeFromFileName(fileName) {
|
|
37
|
+
const baseName = fileName.slice(Math.max(fileName.lastIndexOf("/"), fileName.lastIndexOf("\\")) + 1);
|
|
38
|
+
const separator = baseName.lastIndexOf(".");
|
|
39
|
+
if (separator < 1) return null;
|
|
40
|
+
return mimeTypesByExtension[baseName.slice(separator + 1).toLowerCase()] ?? null;
|
|
41
|
+
}
|
|
42
|
+
async function inspectFileContent(sample, fileName) {
|
|
43
|
+
const { fileTypeFromBuffer, supportedMimeTypes } = await import("file-type");
|
|
44
|
+
const detectableMimeTypes = supportedMimeTypes;
|
|
45
|
+
const detected = await fileTypeFromBuffer(sample.subarray(0, fileContentSampleBytes)).catch(() => void 0);
|
|
46
|
+
const named = fileName ? mimeTypeFromFileName(fileName) : null;
|
|
47
|
+
const mimeType = detected?.mime ?? (named && !detectableMimeTypes.has(named) ? named : null);
|
|
48
|
+
return { mimeType, passive: isPassiveMimeType(mimeType) };
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
fileContentSampleBytes,
|
|
52
|
+
inspectFileContent,
|
|
53
|
+
mimeTypeFromFileName
|
|
54
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/imageDecoding.node.ts
|
|
2
|
+
var maximumDecodedPixels = 4e7;
|
|
3
|
+
var maximumFrames = 1e3;
|
|
4
|
+
var decodedFormatMatchers = Object.freeze({
|
|
5
|
+
"image/avif": (metadata) => metadata.format === "heif" && metadata.compression === "av1",
|
|
6
|
+
"image/gif": (metadata) => metadata.format === "gif",
|
|
7
|
+
"image/jpeg": (metadata) => metadata.format === "jpeg",
|
|
8
|
+
"image/png": (metadata) => metadata.format === "png",
|
|
9
|
+
"image/tiff": (metadata) => metadata.format === "tiff",
|
|
10
|
+
"image/webp": (metadata) => metadata.format === "webp"
|
|
11
|
+
});
|
|
12
|
+
function isMissingModule(error) {
|
|
13
|
+
if (!(error instanceof Error)) return false;
|
|
14
|
+
const code = error.code;
|
|
15
|
+
return code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || isMissingModule(error.cause);
|
|
16
|
+
}
|
|
17
|
+
async function loadSharp() {
|
|
18
|
+
try {
|
|
19
|
+
return (await import("sharp")).default;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (!isMissingModule(error)) throw error;
|
|
22
|
+
throw new Error('[@holo-js/kernel] Server-side image validation requires the optional "sharp" package. Install sharp in your application.', { cause: error });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function skipSubBlocks(bytes, start) {
|
|
26
|
+
let offset = start;
|
|
27
|
+
while (offset < bytes.length) {
|
|
28
|
+
const size = bytes[offset] ?? 0;
|
|
29
|
+
offset += 1;
|
|
30
|
+
if (size === 0) return offset;
|
|
31
|
+
offset += size;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function colorTableBytes(flags) {
|
|
36
|
+
return (flags & 128) === 0 ? 0 : 3 * (1 << (flags & 7) + 1);
|
|
37
|
+
}
|
|
38
|
+
function hasCompleteGifStructure(bytes) {
|
|
39
|
+
let offset = 13 + colorTableBytes(bytes[10] ?? 0);
|
|
40
|
+
while (offset !== null && offset < bytes.length) {
|
|
41
|
+
const introducer = bytes[offset];
|
|
42
|
+
if (introducer === 59) return true;
|
|
43
|
+
if (introducer === 33) {
|
|
44
|
+
offset = skipSubBlocks(bytes, offset + 2);
|
|
45
|
+
} else if (introducer === 44) {
|
|
46
|
+
offset = skipSubBlocks(bytes, offset + 10 + colorTableBytes(bytes[offset + 9] ?? 0) + 1);
|
|
47
|
+
} else {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
async function verifyDecodedImage(contents, mimeType) {
|
|
54
|
+
const matchesDecodedFormat = decodedFormatMatchers[mimeType];
|
|
55
|
+
if (!matchesDecodedFormat) return false;
|
|
56
|
+
if (mimeType === "image/gif" && !hasCompleteGifStructure(contents)) return false;
|
|
57
|
+
const decode = await loadSharp();
|
|
58
|
+
try {
|
|
59
|
+
const image = decode(contents, { animated: true, failOn: "warning", limitInputPixels: maximumDecodedPixels });
|
|
60
|
+
const metadata = await image.metadata();
|
|
61
|
+
if (!matchesDecodedFormat(metadata) || (metadata.pages ?? 1) > maximumFrames) return false;
|
|
62
|
+
await image.stats();
|
|
63
|
+
return true;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
verifyDecodedImage
|
|
70
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -409,4 +409,37 @@ declare function resolveNormalizedRedisConnection(config: NormalizedHoloRedisCon
|
|
|
409
409
|
declare function normalizeRedisConfig(config?: HoloRedisConfig): NormalizedHoloRedisConfig;
|
|
410
410
|
declare function defineRedisConfig<TConfig extends HoloRedisConfig>(config: TConfig): Readonly<TConfig>;
|
|
411
411
|
|
|
412
|
-
|
|
412
|
+
type HoloRequestHeaders = Headers | ReadonlyArray<readonly [string, string]> | Record<string, string | readonly string[] | undefined> | {
|
|
413
|
+
readonly get?: (name: string) => string | null | undefined;
|
|
414
|
+
readonly forEach?: (callback: (value: string, key: string) => void) => void;
|
|
415
|
+
readonly entries?: () => Iterable<readonly [string, string]>;
|
|
416
|
+
};
|
|
417
|
+
type RequestUrlParts = {
|
|
418
|
+
readonly url?: string | URL;
|
|
419
|
+
readonly path?: string;
|
|
420
|
+
readonly headers?: HoloRequestHeaders;
|
|
421
|
+
};
|
|
422
|
+
type HoloRequestInput = RequestUrlParts & {
|
|
423
|
+
readonly request?: Request;
|
|
424
|
+
readonly req?: RequestUrlParts;
|
|
425
|
+
readonly node?: {
|
|
426
|
+
readonly req?: RequestUrlParts;
|
|
427
|
+
};
|
|
428
|
+
readonly web?: {
|
|
429
|
+
readonly request?: RequestUrlParts;
|
|
430
|
+
};
|
|
431
|
+
};
|
|
432
|
+
type HoloTrustedProxyHeaders = 'x-forwarded' | 'forwarded';
|
|
433
|
+
declare function resolveTrustedProxyHeaders(): HoloTrustedProxyHeaders | null;
|
|
434
|
+
declare function readForwardedParameter(headers: HoloRequestHeaders | undefined, name: string): string | undefined;
|
|
435
|
+
declare class HoloRequestUrlError extends TypeError {
|
|
436
|
+
readonly status = 400;
|
|
437
|
+
constructor(message: string);
|
|
438
|
+
}
|
|
439
|
+
declare function resolveRequestUrl(input: HoloRequestInput): URL;
|
|
440
|
+
declare const requestUrlInternals: Readonly<{
|
|
441
|
+
readForwardedParameter: typeof readForwardedParameter;
|
|
442
|
+
resolveTrustedProxyHeaders: typeof resolveTrustedProxyHeaders;
|
|
443
|
+
}>;
|
|
444
|
+
|
|
445
|
+
export { type ConcurrencyOptions, DEFAULT_HOLO_PROJECT_PATHS, DEFAULT_REDIS_CONNECTION, DEFAULT_REDIS_DB, DEFAULT_REDIS_HOST, DEFAULT_REDIS_PORT, type DatabaseLogger, HOLO_PROJECT_PREPARE_API_VERSION, type HoloDatabaseDriver, type HoloGeneratedProjectArtifact, type HoloManagedProjectArtifact, type HoloPluginBroadcastContributions, type HoloPluginCacheContributions, type HoloPluginCliContributions, type HoloPluginConfigContributions, type HoloPluginContributions, type HoloPluginDefinition, type HoloPluginDependencyContributions, type HoloPluginFrameworkContribution, type HoloPluginFrameworkTsconfigKind, type HoloPluginMailContributions, type HoloPluginMigrationContributions, type HoloPluginNotificationContributions, type HoloPluginPackageManager, type HoloPluginProjectContributions, type HoloPluginQueueContributions, type HoloPluginRuntimeContributions, type HoloPluginRuntimeMapContributions, type HoloPluginRuntimeModule, type HoloProjectArtifactContents, type HoloProjectConfig, type HoloProjectConnectionConfig, type HoloProjectDatabaseConfig, type HoloProjectPaths, type HoloProjectPrepareChange, type HoloProjectPrepareChangeKind, type HoloProjectPrepareCommand, type HoloProjectPrepareContext, type HoloProjectPrepareDiagnostic, HoloProjectPrepareError, type HoloProjectPrepareFailure, type HoloProjectPrepareFramework, type HoloProjectPrepareFullRetry, type HoloProjectPrepareLogger, type HoloProjectPrepareModule, type HoloProjectPreparePlugin, type HoloProjectPrepareResult, type HoloProjectPrepareRun, type HoloProjectPrepareSource, type HoloProjectPrepareWatch, type HoloProjectPreparedResult, type HoloProjectPreparer, type HoloRedisClusterNodeConfig, type HoloRedisConfig, type HoloRedisConnectionConfig, type HoloRequestHeaders, type HoloRequestInput, HoloRequestUrlError, type HoloTrustedProxyHeaders, type LoadedHoloPluginDefinition, type MigrationErrorLog, type MigrationStartLog, type MigrationSuccessLog, type NormalizedHoloProjectConfig, type NormalizedHoloRedisClusterNodeConfig, type NormalizedHoloRedisConfig, type NormalizedHoloRedisConnectionConfig, type PluginLoadOptions, type QueryErrorLog, type QueryStartLog, type QuerySuccessLog, type RuntimeContribution, RuntimeLifecycle, type RuntimeLifecycleContext, type SeederErrorLog, type SeederStartLog, type SeederSuccessLog, type TransactionLog, type TransactionScopeKind, createRuntimeLifecycle, defineHoloPlugin, defineHoloProject, defineHoloProjectPreparer, defineRedisConfig, holoRedisDefaults, loadHoloPluginBootModules, loadHoloPluginContributionModules, loadHoloPluginDefinitions, normalizeHoloPluginDefinition, normalizeHoloProjectConfig, normalizeRedisConfig, requestUrlInternals, resolveHoloPluginModulePath, resolveNormalizedRedisConnection, resolveRequestUrl };
|
package/dist/index.mjs
CHANGED
|
@@ -426,6 +426,134 @@ function normalizeRedisConfig(config = {}) {
|
|
|
426
426
|
function defineRedisConfig(config) {
|
|
427
427
|
return Object.freeze({ ...config });
|
|
428
428
|
}
|
|
429
|
+
|
|
430
|
+
// src/requestUrl.ts
|
|
431
|
+
function resolveTrustedProxyHeaders() {
|
|
432
|
+
const value = typeof process === "undefined" ? void 0 : process.env.HOLO_SECURITY_TRUST_PROXY?.trim().toLowerCase();
|
|
433
|
+
if (value === "forwarded") return "forwarded";
|
|
434
|
+
if (value === "x-forwarded" || value === "1" || value === "true" || value === "yes" || value === "on") return "x-forwarded";
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
function isHeaderTuples(headers) {
|
|
438
|
+
return Array.isArray(headers);
|
|
439
|
+
}
|
|
440
|
+
function readHeader(headers, name) {
|
|
441
|
+
if (!headers) return void 0;
|
|
442
|
+
if (isHeaderTuples(headers)) {
|
|
443
|
+
return headers.find(([key]) => key.toLowerCase() === name)?.[1];
|
|
444
|
+
}
|
|
445
|
+
if ("get" in headers && typeof headers.get === "function") return headers.get(name) ?? void 0;
|
|
446
|
+
if ("entries" in headers && typeof headers.entries === "function") {
|
|
447
|
+
for (const [key, value] of headers.entries()) {
|
|
448
|
+
if (key.toLowerCase() === name) return value;
|
|
449
|
+
}
|
|
450
|
+
return void 0;
|
|
451
|
+
}
|
|
452
|
+
if ("forEach" in headers && typeof headers.forEach === "function") {
|
|
453
|
+
let result;
|
|
454
|
+
headers.forEach((value, key) => {
|
|
455
|
+
if (key.toLowerCase() === name) result = value;
|
|
456
|
+
});
|
|
457
|
+
return result;
|
|
458
|
+
}
|
|
459
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
460
|
+
if (key.toLowerCase() === name) {
|
|
461
|
+
return typeof value === "string" ? value : Array.isArray(value) ? value.join(",") : void 0;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return void 0;
|
|
465
|
+
}
|
|
466
|
+
function firstForwardedValue(value) {
|
|
467
|
+
return value?.split(",", 1)[0]?.trim().replace(/^"|"$/g, "");
|
|
468
|
+
}
|
|
469
|
+
function firstForwardedElement(value) {
|
|
470
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
471
|
+
let key = "";
|
|
472
|
+
let current = "";
|
|
473
|
+
let readingValue = false;
|
|
474
|
+
let quoted = false;
|
|
475
|
+
let escaped = false;
|
|
476
|
+
const commit = () => {
|
|
477
|
+
const name = key.trim().toLowerCase();
|
|
478
|
+
if (readingValue && name && !pairs.has(name)) pairs.set(name, current.trim());
|
|
479
|
+
key = "";
|
|
480
|
+
current = "";
|
|
481
|
+
readingValue = false;
|
|
482
|
+
};
|
|
483
|
+
for (const character of value) {
|
|
484
|
+
if (escaped) {
|
|
485
|
+
current += character;
|
|
486
|
+
escaped = false;
|
|
487
|
+
} else if (quoted) {
|
|
488
|
+
if (character === "\\") escaped = true;
|
|
489
|
+
else if (character === '"') quoted = false;
|
|
490
|
+
else current += character;
|
|
491
|
+
} else if (character === ",") {
|
|
492
|
+
break;
|
|
493
|
+
} else if (character === ";") {
|
|
494
|
+
commit();
|
|
495
|
+
} else if (character === "=" && !readingValue) {
|
|
496
|
+
readingValue = true;
|
|
497
|
+
} else if (character === '"' && readingValue) {
|
|
498
|
+
quoted = true;
|
|
499
|
+
} else if (readingValue) {
|
|
500
|
+
current += character;
|
|
501
|
+
} else {
|
|
502
|
+
key += character;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
commit();
|
|
506
|
+
return pairs;
|
|
507
|
+
}
|
|
508
|
+
function readForwardedParameter(headers, name) {
|
|
509
|
+
const forwarded = readHeader(headers, "forwarded");
|
|
510
|
+
return forwarded === void 0 ? void 0 : firstForwardedElement(forwarded).get(name);
|
|
511
|
+
}
|
|
512
|
+
function readTrustedProxyValue(headers, trustedProxyHeaders, name) {
|
|
513
|
+
if (trustedProxyHeaders === "forwarded") return readForwardedParameter(headers, name);
|
|
514
|
+
if (trustedProxyHeaders === "x-forwarded") return firstForwardedValue(readHeader(headers, `x-forwarded-${name}`));
|
|
515
|
+
return void 0;
|
|
516
|
+
}
|
|
517
|
+
var HoloRequestUrlError = class extends TypeError {
|
|
518
|
+
status = 400;
|
|
519
|
+
constructor(message) {
|
|
520
|
+
super(`[@holo-js/kernel] ${message}`);
|
|
521
|
+
this.name = "HoloRequestUrlError";
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
var invalidRequestHostMessage = "Request hosts must be a valid hostname and optional port.";
|
|
525
|
+
function parseRequestUrl(value, invalidMessage) {
|
|
526
|
+
if (!URL.canParse(String(value), "http://localhost")) throw new HoloRequestUrlError(invalidMessage);
|
|
527
|
+
return new URL(value, "http://localhost");
|
|
528
|
+
}
|
|
529
|
+
function resolveRequestUrl(input) {
|
|
530
|
+
const nested = input instanceof Request ? void 0 : input.request ?? input.web?.request ?? input.req ?? input.node?.req;
|
|
531
|
+
const headers = input.headers ?? nested?.headers;
|
|
532
|
+
const value = input.url ?? nested?.url ?? input.path ?? (nested && "path" in nested ? nested.path : void 0) ?? "/";
|
|
533
|
+
const invalidUrlMessage = "Request URLs must use http or https without credentials.";
|
|
534
|
+
const url = parseRequestUrl(value, invalidUrlMessage);
|
|
535
|
+
if (url.username || url.password || url.protocol !== "http:" && url.protocol !== "https:") {
|
|
536
|
+
throw new HoloRequestUrlError(invalidUrlMessage);
|
|
537
|
+
}
|
|
538
|
+
const trustedProxyHeaders = resolveTrustedProxyHeaders();
|
|
539
|
+
const protocol = (readTrustedProxyValue(headers, trustedProxyHeaders, "proto") ?? url.protocol.slice(0, -1)).toLowerCase();
|
|
540
|
+
if (protocol !== "http" && protocol !== "https") {
|
|
541
|
+
throw new HoloRequestUrlError("Request protocols must be http or https.");
|
|
542
|
+
}
|
|
543
|
+
const host = readTrustedProxyValue(headers, trustedProxyHeaders, "host") ?? readHeader(headers, "host") ?? url.host;
|
|
544
|
+
if (!host || /[\s,/@\\?#]/u.test(host)) {
|
|
545
|
+
throw new HoloRequestUrlError(invalidRequestHostMessage);
|
|
546
|
+
}
|
|
547
|
+
const origin = parseRequestUrl(`${protocol}://${host}`, invalidRequestHostMessage);
|
|
548
|
+
if (origin.pathname !== "/" || origin.username || origin.password || origin.search || origin.hash) {
|
|
549
|
+
throw new HoloRequestUrlError(invalidRequestHostMessage);
|
|
550
|
+
}
|
|
551
|
+
url.protocol = origin.protocol;
|
|
552
|
+
url.host = origin.host;
|
|
553
|
+
url.port = origin.port;
|
|
554
|
+
return url;
|
|
555
|
+
}
|
|
556
|
+
var requestUrlInternals = Object.freeze({ readForwardedParameter, resolveTrustedProxyHeaders });
|
|
429
557
|
export {
|
|
430
558
|
DEFAULT_HOLO_PROJECT_PATHS,
|
|
431
559
|
DEFAULT_REDIS_CONNECTION,
|
|
@@ -434,6 +562,7 @@ export {
|
|
|
434
562
|
DEFAULT_REDIS_PORT,
|
|
435
563
|
HOLO_PROJECT_PREPARE_API_VERSION,
|
|
436
564
|
HoloProjectPrepareError,
|
|
565
|
+
HoloRequestUrlError,
|
|
437
566
|
RuntimeLifecycle,
|
|
438
567
|
createRuntimeLifecycle,
|
|
439
568
|
defineHoloPlugin,
|
|
@@ -449,6 +578,8 @@ export {
|
|
|
449
578
|
normalizeHoloPluginDefinition,
|
|
450
579
|
normalizeHoloProjectConfig,
|
|
451
580
|
normalizeRedisConfig,
|
|
581
|
+
requestUrlInternals,
|
|
452
582
|
resolveHoloPluginModulePath,
|
|
453
|
-
resolveNormalizedRedisConnection
|
|
583
|
+
resolveNormalizedRedisConnection,
|
|
584
|
+
resolveRequestUrl
|
|
454
585
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/kernel",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.28",
|
|
4
4
|
"description": "Holo-JS Framework - dependency-free contracts, plugins, and runtime lifecycle",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,6 +14,17 @@
|
|
|
14
14
|
"types": "./dist/http-errors.d.ts",
|
|
15
15
|
"import": "./dist/http-errors.mjs",
|
|
16
16
|
"default": "./dist/http-errors.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./file-content": {
|
|
19
|
+
"types": "./dist/file-content.d.ts",
|
|
20
|
+
"import": "./dist/file-content.mjs",
|
|
21
|
+
"default": "./dist/file-content.mjs"
|
|
22
|
+
},
|
|
23
|
+
"./image-decoding": {
|
|
24
|
+
"types": "./dist/image-decoding.d.ts",
|
|
25
|
+
"browser": "./dist/image-decoding.browser.mjs",
|
|
26
|
+
"node": "./dist/image-decoding.node.mjs",
|
|
27
|
+
"default": "./dist/image-decoding.mjs"
|
|
17
28
|
}
|
|
18
29
|
},
|
|
19
30
|
"main": "./dist/index.mjs",
|
|
@@ -29,11 +40,25 @@
|
|
|
29
40
|
},
|
|
30
41
|
"devDependencies": {
|
|
31
42
|
"@types/node": "^22.10.2",
|
|
43
|
+
"file-type": "^22.2.0",
|
|
44
|
+
"sharp": "^0.35.4",
|
|
32
45
|
"tsup": "^8.3.5",
|
|
33
46
|
"typescript": "^5.7.2",
|
|
34
47
|
"vitest": "^4.1.5"
|
|
35
48
|
},
|
|
36
49
|
"engines": {
|
|
37
50
|
"node": "^22.12.0 || ^24.0.0 || ^26.0.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"file-type": "^22.2.0",
|
|
54
|
+
"sharp": "^0.35.4"
|
|
55
|
+
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"file-type": {
|
|
58
|
+
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"sharp": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
38
63
|
}
|
|
39
64
|
}
|