@spring-systems/core 0.8.6 → 0.8.7
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/adapters/index.js +1 -56
- package/dist/auth/index.js +1 -19
- package/dist/chunk-3OMNT22N.js +1 -0
- package/dist/chunk-4KRUU6MS.js +1 -0
- package/dist/chunk-6J2VFOKL.js +1 -0
- package/dist/chunk-7P4BJDQR.js +1 -0
- package/dist/chunk-AMXSATFF.js +1 -0
- package/dist/chunk-BMIRKMVX.js +1 -0
- package/dist/chunk-EVDFSWPU.js +1 -0
- package/dist/chunk-F3VXVDPQ.js +1 -0
- package/dist/chunk-GSQE2NEY.js +1 -0
- package/dist/chunk-HUASNNWD.js +1 -0
- package/dist/chunk-ICKHSEIX.js +1 -0
- package/dist/chunk-JRHMAY5G.js +1 -0
- package/dist/chunk-MNLYYTGZ.js +7 -0
- package/dist/chunk-OOVZTF74.js +1 -0
- package/dist/chunk-PNDXLNCU.js +1 -0
- package/dist/chunk-R3XYEEGR.js +1 -0
- package/dist/chunk-RKLYBW3O.js +1 -0
- package/dist/chunk-RVQHSQYF.js +3 -0
- package/dist/chunk-UT6X6RQM.js +1 -0
- package/dist/chunk-Y6DB43IE.js +3 -0
- package/dist/chunk-YMSSF2ZU.js +1 -0
- package/dist/config/index.js +1 -109
- package/dist/devtools/index.js +1 -67
- package/dist/errors/index.js +1 -21
- package/dist/events/index.js +1 -12
- package/dist/i18n/index.js +1 -7
- package/dist/index.js +1 -42
- package/dist/instance/index.js +1 -37
- package/dist/logger/index.js +1 -27
- package/dist/middleware/index.js +1 -23
- package/dist/plugins/index.js +1 -16
- package/dist/testing/index.js +1 -171
- package/dist/types/index.js +1 -72
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -772
- package/dist/validation/index.js +1 -147
- package/package.json +137 -136
- package/dist/adapters/index.js.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/chunk-2PJWFA5S.js +0 -393
- package/dist/chunk-2PJWFA5S.js.map +0 -1
- package/dist/chunk-EFUBAQCV.js +0 -94
- package/dist/chunk-EFUBAQCV.js.map +0 -1
- package/dist/chunk-F2SIMWZ5.js +0 -173
- package/dist/chunk-F2SIMWZ5.js.map +0 -1
- package/dist/chunk-F7WUQJH7.js +0 -399
- package/dist/chunk-F7WUQJH7.js.map +0 -1
- package/dist/chunk-GON7Q32Q.js +0 -176
- package/dist/chunk-GON7Q32Q.js.map +0 -1
- package/dist/chunk-GXU75LQX.js +0 -182
- package/dist/chunk-GXU75LQX.js.map +0 -1
- package/dist/chunk-HFELOXDQ.js +0 -110
- package/dist/chunk-HFELOXDQ.js.map +0 -1
- package/dist/chunk-KX32MU3I.js +0 -190
- package/dist/chunk-KX32MU3I.js.map +0 -1
- package/dist/chunk-MEWPYTWC.js +0 -284
- package/dist/chunk-MEWPYTWC.js.map +0 -1
- package/dist/chunk-N2L4TUC4.js +0 -34
- package/dist/chunk-N2L4TUC4.js.map +0 -1
- package/dist/chunk-NQQIVCLX.js +0 -47
- package/dist/chunk-NQQIVCLX.js.map +0 -1
- package/dist/chunk-OSSX443T.js +0 -146
- package/dist/chunk-OSSX443T.js.map +0 -1
- package/dist/chunk-PT4DIYUK.js +0 -78
- package/dist/chunk-PT4DIYUK.js.map +0 -1
- package/dist/chunk-QAVWXARR.js +0 -51
- package/dist/chunk-QAVWXARR.js.map +0 -1
- package/dist/chunk-RRWKDFAB.js +0 -143
- package/dist/chunk-RRWKDFAB.js.map +0 -1
- package/dist/chunk-RUCXSQEY.js +0 -42
- package/dist/chunk-RUCXSQEY.js.map +0 -1
- package/dist/chunk-S6RPCN5H.js +0 -64
- package/dist/chunk-S6RPCN5H.js.map +0 -1
- package/dist/chunk-S7MKRNMI.js +0 -153
- package/dist/chunk-S7MKRNMI.js.map +0 -1
- package/dist/chunk-SQB4F3EF.js +0 -55
- package/dist/chunk-SQB4F3EF.js.map +0 -1
- package/dist/chunk-UDT2RPX2.js +0 -43
- package/dist/chunk-UDT2RPX2.js.map +0 -1
- package/dist/chunk-VRMVN2UM.js +0 -17
- package/dist/chunk-VRMVN2UM.js.map +0 -1
- package/dist/config/index.js.map +0 -1
- package/dist/devtools/index.js.map +0 -1
- package/dist/errors/index.js.map +0 -1
- package/dist/events/index.js.map +0 -1
- package/dist/i18n/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/instance/index.js.map +0 -1
- package/dist/logger/index.js.map +0 -1
- package/dist/middleware/index.js.map +0 -1
- package/dist/plugins/index.js.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/validation/index.js.map +0 -1
package/dist/chunk-KX32MU3I.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
tryGetSpringInstance
|
|
3
|
-
} from "./chunk-EFUBAQCV.js";
|
|
4
|
-
|
|
5
|
-
// src/utils/security-sanitize.ts
|
|
6
|
-
function isSensitiveSecurityKey(key) {
|
|
7
|
-
const normalized = key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").toLowerCase();
|
|
8
|
-
const parts = new Set(normalized.split("_").filter(Boolean));
|
|
9
|
-
const has = (part) => parts.has(part);
|
|
10
|
-
if (has("token") || has("secret") || has("password") || has("cookie") || has("session")) {
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
if (has("authorization")) {
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
if (has("credential") || has("credentials")) {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
if (has("api") && has("key")) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
if ((has("access") || has("refresh")) && has("token")) {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
if (has("auth") && (has("token") || has("header") || has("session"))) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
function sanitizeSecurityData(data) {
|
|
31
|
-
if (!data) return void 0;
|
|
32
|
-
const visiting = /* @__PURE__ */ new WeakSet();
|
|
33
|
-
function isSensitiveStringValue(value) {
|
|
34
|
-
const trimmed = value.trim();
|
|
35
|
-
if (!trimmed) return false;
|
|
36
|
-
if (/^Bearer\s+\S+$/i.test(trimmed)) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
const withoutBearer = trimmed.replace(/^Bearer\s+/i, "");
|
|
40
|
-
if (withoutBearer.length >= 24 && /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(withoutBearer)) {
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
if (withoutBearer.length >= 40 && !/\s/.test(withoutBearer) && !/^https?:\/\//i.test(withoutBearer) && /^[A-Za-z0-9._~+/-]+=*$/.test(withoutBearer)) {
|
|
44
|
-
const uniqueChars = new Set(withoutBearer).size;
|
|
45
|
-
const hasDigit = /\d/.test(withoutBearer);
|
|
46
|
-
const hasSymbol = /[._~+/-]/.test(withoutBearer);
|
|
47
|
-
if (uniqueChars >= 6 && (hasDigit || hasSymbol)) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
function sanitizeValue(key, value) {
|
|
54
|
-
if (key && isSensitiveSecurityKey(key)) {
|
|
55
|
-
return "[REDACTED]";
|
|
56
|
-
}
|
|
57
|
-
if (typeof value === "string") {
|
|
58
|
-
if (isSensitiveStringValue(value)) {
|
|
59
|
-
return "[REDACTED]";
|
|
60
|
-
}
|
|
61
|
-
if (value.length > 120) {
|
|
62
|
-
return `${value.slice(0, 117)}...`;
|
|
63
|
-
}
|
|
64
|
-
return value;
|
|
65
|
-
}
|
|
66
|
-
if (value === null || typeof value !== "object") {
|
|
67
|
-
return value;
|
|
68
|
-
}
|
|
69
|
-
if (visiting.has(value)) {
|
|
70
|
-
return "[Circular]";
|
|
71
|
-
}
|
|
72
|
-
visiting.add(value);
|
|
73
|
-
try {
|
|
74
|
-
if (Array.isArray(value)) {
|
|
75
|
-
return value.map((item) => sanitizeValue(key, item));
|
|
76
|
-
}
|
|
77
|
-
const nested = {};
|
|
78
|
-
for (const [nestedKey, nestedValue] of Object.entries(value)) {
|
|
79
|
-
nested[nestedKey] = sanitizeValue(nestedKey, nestedValue);
|
|
80
|
-
}
|
|
81
|
-
return nested;
|
|
82
|
-
} finally {
|
|
83
|
-
visiting.delete(value);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return sanitizeValue(void 0, data);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/logger/logger.ts
|
|
90
|
-
var logLevelPriority = {
|
|
91
|
-
debug: 0,
|
|
92
|
-
info: 1,
|
|
93
|
-
warn: 2,
|
|
94
|
-
error: 3,
|
|
95
|
-
silent: 4
|
|
96
|
-
};
|
|
97
|
-
function isProductionRuntime() {
|
|
98
|
-
const globalProcess = globalThis.process;
|
|
99
|
-
const nodeEnv = globalProcess?.env?.NODE_ENV;
|
|
100
|
-
if (nodeEnv === "production") {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
if (typeof nodeEnv === "string") {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
const importMetaEnv = import.meta.env;
|
|
107
|
-
if (!importMetaEnv) {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
return importMetaEnv.PROD === true || importMetaEnv.MODE === "production" || importMetaEnv.NODE_ENV === "production";
|
|
111
|
-
}
|
|
112
|
-
var DEFAULT_LOG_LEVEL = isProductionRuntime() ? "info" : "debug";
|
|
113
|
-
var currentLogLevel = DEFAULT_LOG_LEVEL;
|
|
114
|
-
function setLogLevel(level) {
|
|
115
|
-
currentLogLevel = level;
|
|
116
|
-
}
|
|
117
|
-
function getLogLevel() {
|
|
118
|
-
return currentLogLevel;
|
|
119
|
-
}
|
|
120
|
-
function isLevelEnabled(level) {
|
|
121
|
-
return logLevelPriority[level] >= logLevelPriority[currentLogLevel];
|
|
122
|
-
}
|
|
123
|
-
var fallbackAdapter = {};
|
|
124
|
-
function setLogAdapter(a) {
|
|
125
|
-
const instance = tryGetSpringInstance();
|
|
126
|
-
if (instance) {
|
|
127
|
-
instance.core.logAdapter = a;
|
|
128
|
-
} else {
|
|
129
|
-
fallbackAdapter = a;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function getAdapter() {
|
|
133
|
-
const instance = tryGetSpringInstance();
|
|
134
|
-
if (!instance) return fallbackAdapter;
|
|
135
|
-
return { ...fallbackAdapter, ...instance.core.logAdapter };
|
|
136
|
-
}
|
|
137
|
-
function clearLogAdapter() {
|
|
138
|
-
const instance = tryGetSpringInstance();
|
|
139
|
-
if (instance) {
|
|
140
|
-
instance.core.logAdapter = {};
|
|
141
|
-
}
|
|
142
|
-
fallbackAdapter = {};
|
|
143
|
-
}
|
|
144
|
-
function resetLogLevel() {
|
|
145
|
-
currentLogLevel = DEFAULT_LOG_LEVEL;
|
|
146
|
-
}
|
|
147
|
-
function timestamp() {
|
|
148
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
149
|
-
}
|
|
150
|
-
function logDebug(context, data) {
|
|
151
|
-
if (!isLevelEnabled("debug")) return;
|
|
152
|
-
console.debug(`[${timestamp()}] [${context}]`, data ?? "");
|
|
153
|
-
}
|
|
154
|
-
function logError(context, error) {
|
|
155
|
-
getAdapter().onError?.(context, error);
|
|
156
|
-
if (!isLevelEnabled("error")) return;
|
|
157
|
-
console.error(`[${timestamp()}] [${context}]`, error ?? "");
|
|
158
|
-
}
|
|
159
|
-
function logWarn(context, message) {
|
|
160
|
-
getAdapter().onWarn?.(context, message);
|
|
161
|
-
if (!isLevelEnabled("warn")) return;
|
|
162
|
-
console.warn(`[${timestamp()}] [${context}]`, message ?? "");
|
|
163
|
-
}
|
|
164
|
-
function logInfo(context, data) {
|
|
165
|
-
if (!isLevelEnabled("info")) return;
|
|
166
|
-
console.info(`[${timestamp()}] [${context}]`, data ?? "");
|
|
167
|
-
}
|
|
168
|
-
function logSecurityEvent(event, data) {
|
|
169
|
-
const sanitized = sanitizeSecurityData(data);
|
|
170
|
-
if (isLevelEnabled("info")) {
|
|
171
|
-
console.info(`[${timestamp()}] [SECURITY] ${event}`, sanitized ?? "");
|
|
172
|
-
}
|
|
173
|
-
getAdapter().onSecurityEvent?.(event, sanitized);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export {
|
|
177
|
-
isSensitiveSecurityKey,
|
|
178
|
-
sanitizeSecurityData,
|
|
179
|
-
setLogLevel,
|
|
180
|
-
getLogLevel,
|
|
181
|
-
setLogAdapter,
|
|
182
|
-
clearLogAdapter,
|
|
183
|
-
resetLogLevel,
|
|
184
|
-
logDebug,
|
|
185
|
-
logError,
|
|
186
|
-
logWarn,
|
|
187
|
-
logInfo,
|
|
188
|
-
logSecurityEvent
|
|
189
|
-
};
|
|
190
|
-
//# sourceMappingURL=chunk-KX32MU3I.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/security-sanitize.ts","../src/logger/logger.ts"],"sourcesContent":["export type SecurityLogScalar = string | number | boolean | null;\nexport interface SecurityLogData {\n [key: string]: SecurityLogValue;\n}\nexport type SecurityLogValue = SecurityLogScalar | SecurityLogData | SecurityLogValue[];\n\nexport function isSensitiveSecurityKey(key: string): boolean {\n const normalized = key\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .toLowerCase();\n\n const parts = new Set(normalized.split(\"_\").filter(Boolean));\n const has = (part: string): boolean => parts.has(part);\n\n if (has(\"token\") || has(\"secret\") || has(\"password\") || has(\"cookie\") || has(\"session\")) {\n return true;\n }\n if (has(\"authorization\")) {\n return true;\n }\n if (has(\"credential\") || has(\"credentials\")) {\n return true;\n }\n if (has(\"api\") && has(\"key\")) {\n return true;\n }\n if ((has(\"access\") || has(\"refresh\")) && has(\"token\")) {\n return true;\n }\n if (has(\"auth\") && (has(\"token\") || has(\"header\") || has(\"session\"))) {\n return true;\n }\n\n return false;\n}\n\nexport function sanitizeSecurityData(data?: SecurityLogData): SecurityLogData | undefined {\n if (!data) return undefined;\n\n const visiting = new WeakSet<object>();\n\n function isSensitiveStringValue(value: string): boolean {\n const trimmed = value.trim();\n if (!trimmed) return false;\n\n if (/^Bearer\\s+\\S+$/i.test(trimmed)) {\n return true;\n }\n\n const withoutBearer = trimmed.replace(/^Bearer\\s+/i, \"\");\n if (\n withoutBearer.length >= 24 &&\n /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(withoutBearer)\n ) {\n return true;\n }\n\n if (\n withoutBearer.length >= 40 &&\n !/\\s/.test(withoutBearer) &&\n !/^https?:\\/\\//i.test(withoutBearer) &&\n /^[A-Za-z0-9._~+/-]+=*$/.test(withoutBearer)\n ) {\n const uniqueChars = new Set(withoutBearer).size;\n const hasDigit = /\\d/.test(withoutBearer);\n const hasSymbol = /[._~+/-]/.test(withoutBearer);\n if (uniqueChars >= 6 && (hasDigit || hasSymbol)) {\n return true;\n }\n }\n\n return false;\n }\n\n function sanitizeValue(key: string | undefined, value: SecurityLogValue): SecurityLogValue {\n if (key && isSensitiveSecurityKey(key)) {\n return \"[REDACTED]\";\n }\n\n if (typeof value === \"string\") {\n if (isSensitiveStringValue(value)) {\n return \"[REDACTED]\";\n }\n if (value.length > 120) {\n return `${value.slice(0, 117)}...`;\n }\n return value;\n }\n\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n\n if (visiting.has(value)) {\n return \"[Circular]\";\n }\n visiting.add(value);\n\n try {\n if (Array.isArray(value)) {\n return value.map((item) => sanitizeValue(key, item));\n }\n\n const nested: SecurityLogData = {};\n for (const [nestedKey, nestedValue] of Object.entries(value)) {\n nested[nestedKey] = sanitizeValue(nestedKey, nestedValue as SecurityLogValue);\n }\n return nested;\n } finally {\n visiting.delete(value);\n }\n }\n\n return sanitizeValue(undefined, data) as SecurityLogData;\n}\n","/**\n * Console wrapper with timestamp and configurable log levels.\n * @module logger\n */\n\nimport { tryGetSpringInstance } from \"../instance/current-instance\";\nimport type { SecurityEventType } from \"../instance/spring-instance\";\nimport { sanitizeSecurityData, type SecurityLogData } from \"../utils/security-sanitize\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\ntype BivariantCallback<TArgs extends unknown[], TResult = void> = {\n bivarianceHack: (...args: TArgs) => TResult;\n}[\"bivarianceHack\"];\n\nexport interface LogAdapter {\n onError?: (context: string, error?: unknown) => void;\n onWarn?: (context: string, message?: string) => void;\n // Bivariant for backward compatibility with older narrower callback signatures.\n onSecurityEvent?: BivariantCallback<[event: SecurityEventType, data?: SecurityLogData]>;\n}\n\nconst logLevelPriority = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n} satisfies Record<LogLevel, number>;\n\nfunction isProductionRuntime(): boolean {\n const globalProcess = (globalThis as { process?: { env?: Record<string, unknown> } }).process;\n const nodeEnv = globalProcess?.env?.NODE_ENV;\n if (nodeEnv === \"production\") {\n return true;\n }\n if (typeof nodeEnv === \"string\") {\n return false;\n }\n\n const importMetaEnv = (import.meta as ImportMeta & { env?: Record<string, unknown> }).env;\n if (!importMetaEnv) {\n // Library default should be conservative when runtime env cannot be detected.\n return true;\n }\n\n return (\n importMetaEnv.PROD === true ||\n importMetaEnv.MODE === \"production\" ||\n importMetaEnv.NODE_ENV === \"production\"\n );\n}\n\nconst DEFAULT_LOG_LEVEL: LogLevel =\n isProductionRuntime() ? \"info\" : \"debug\";\n\nlet currentLogLevel: LogLevel = DEFAULT_LOG_LEVEL;\n\n/**\n * Set the minimum log level. Messages below this level are suppressed.\n * Default is \"info\" in production, \"debug\" in development.\n */\nexport function setLogLevel(level: LogLevel): void {\n currentLogLevel = level;\n}\n\n/**\n * Get the current log level.\n */\nexport function getLogLevel(): LogLevel {\n return currentLogLevel;\n}\n\nfunction isLevelEnabled(level: LogLevel): boolean {\n return logLevelPriority[level] >= logLevelPriority[currentLogLevel];\n}\n\nlet fallbackAdapter: LogAdapter = {};\n\nexport function setLogAdapter(a: LogAdapter): void {\n const instance = tryGetSpringInstance();\n if (instance) {\n instance.core.logAdapter = a;\n } else {\n fallbackAdapter = a;\n }\n}\n\nfunction getAdapter(): LogAdapter {\n const instance = tryGetSpringInstance();\n if (!instance) return fallbackAdapter;\n return { ...fallbackAdapter, ...instance.core.logAdapter };\n}\n\n/**\n * Reset adapter callbacks to defaults (no-op adapter).\n * For testing/integration teardown only.\n */\nexport function clearLogAdapter(): void {\n const instance = tryGetSpringInstance();\n if (instance) {\n instance.core.logAdapter = {};\n }\n fallbackAdapter = {};\n}\n\n/** Reset log level to runtime default (info in prod, debug otherwise). */\nexport function resetLogLevel(): void {\n currentLogLevel = DEFAULT_LOG_LEVEL;\n}\n\nfunction timestamp(): string {\n return new Date().toISOString();\n}\n\nexport function logDebug(context: string, data?: unknown): void {\n if (!isLevelEnabled(\"debug\")) return;\n console.debug(`[${timestamp()}] [${context}]`, data ?? \"\");\n}\n\nexport function logError(context: string, error?: unknown): void {\n getAdapter().onError?.(context, error);\n if (!isLevelEnabled(\"error\")) return;\n console.error(`[${timestamp()}] [${context}]`, error ?? \"\");\n}\n\nexport function logWarn(context: string, message?: string): void {\n getAdapter().onWarn?.(context, message);\n if (!isLevelEnabled(\"warn\")) return;\n console.warn(`[${timestamp()}] [${context}]`, message ?? \"\");\n}\n\nexport function logInfo(context: string, data?: unknown): void {\n if (!isLevelEnabled(\"info\")) return;\n console.info(`[${timestamp()}] [${context}]`, data ?? \"\");\n}\n\nexport function logSecurityEvent(event: SecurityEventType, data?: SecurityLogData): void {\n const sanitized = sanitizeSecurityData(data);\n // Security events always log regardless of level (they go through the adapter)\n if (isLevelEnabled(\"info\")) {\n console.info(`[${timestamp()}] [SECURITY] ${event}`, sanitized ?? \"\");\n }\n getAdapter().onSecurityEvent?.(event, sanitized);\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-MEWPYTWC.js
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
registerFallbackMigration
|
|
3
|
-
} from "./chunk-RUCXSQEY.js";
|
|
4
|
-
import {
|
|
5
|
-
devThrow,
|
|
6
|
-
tryGetSpringInstance
|
|
7
|
-
} from "./chunk-EFUBAQCV.js";
|
|
8
|
-
import {
|
|
9
|
-
SpringMiddlewareError
|
|
10
|
-
} from "./chunk-PT4DIYUK.js";
|
|
11
|
-
|
|
12
|
-
// src/middleware/middleware-runner.ts
|
|
13
|
-
function composeMiddleware(middlewares, options) {
|
|
14
|
-
const timeoutMs = options?.timeoutMs;
|
|
15
|
-
return async (ctx) => {
|
|
16
|
-
let index = -1;
|
|
17
|
-
let timedOut = false;
|
|
18
|
-
const timeoutController = timeoutMs != null && timeoutMs > 0 && typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
19
|
-
const restoreSignal = timeoutController ? attachTimeoutSignal(ctx, timeoutController.signal) : () => {
|
|
20
|
-
};
|
|
21
|
-
const createTimeoutError = () => new SpringMiddlewareError(
|
|
22
|
-
`Middleware chain timed out after ${timeoutMs}ms`,
|
|
23
|
-
"timeout"
|
|
24
|
-
);
|
|
25
|
-
async function dispatch(i) {
|
|
26
|
-
if (timedOut) {
|
|
27
|
-
throw createTimeoutError();
|
|
28
|
-
}
|
|
29
|
-
if (i <= index) {
|
|
30
|
-
throw new SpringMiddlewareError("next() called multiple times in middleware.", "compose");
|
|
31
|
-
}
|
|
32
|
-
index = i;
|
|
33
|
-
if (i >= middlewares.length) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const fn = middlewares[i];
|
|
37
|
-
if (!fn) return;
|
|
38
|
-
await fn(ctx, () => dispatch(i + 1));
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
if (timeoutMs != null && timeoutMs > 0) {
|
|
42
|
-
await raceWithTimeout(dispatch(0), timeoutMs, () => {
|
|
43
|
-
timedOut = true;
|
|
44
|
-
timeoutController?.abort();
|
|
45
|
-
});
|
|
46
|
-
} else {
|
|
47
|
-
await dispatch(0);
|
|
48
|
-
}
|
|
49
|
-
} finally {
|
|
50
|
-
restoreSignal();
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
function isAbortSignalLike(value) {
|
|
55
|
-
if (!value || typeof value !== "object") return false;
|
|
56
|
-
const candidate = value;
|
|
57
|
-
return typeof candidate.aborted === "boolean" && typeof candidate.addEventListener === "function";
|
|
58
|
-
}
|
|
59
|
-
function canAssignSignal(target) {
|
|
60
|
-
let current = target;
|
|
61
|
-
while (current) {
|
|
62
|
-
const descriptor = Object.getOwnPropertyDescriptor(current, "signal");
|
|
63
|
-
if (!descriptor) {
|
|
64
|
-
current = Object.getPrototypeOf(current);
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
if ("set" in descriptor) {
|
|
68
|
-
return typeof descriptor.set === "function";
|
|
69
|
-
}
|
|
70
|
-
return descriptor.writable === true;
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
function mergeAbortSignals(existing, timeoutSignal) {
|
|
75
|
-
if (typeof AbortSignal !== "undefined" && typeof AbortSignal.any === "function") {
|
|
76
|
-
return { signal: AbortSignal.any([existing, timeoutSignal]), cleanup: () => {
|
|
77
|
-
} };
|
|
78
|
-
}
|
|
79
|
-
if (typeof AbortController === "undefined") {
|
|
80
|
-
return { signal: timeoutSignal, cleanup: () => {
|
|
81
|
-
} };
|
|
82
|
-
}
|
|
83
|
-
const controller = new AbortController();
|
|
84
|
-
const abortCombined = () => {
|
|
85
|
-
if (!controller.signal.aborted) {
|
|
86
|
-
controller.abort();
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
if (existing.aborted || timeoutSignal.aborted) {
|
|
90
|
-
abortCombined();
|
|
91
|
-
return { signal: controller.signal, cleanup: () => {
|
|
92
|
-
} };
|
|
93
|
-
}
|
|
94
|
-
existing.addEventListener("abort", abortCombined, { once: true });
|
|
95
|
-
timeoutSignal.addEventListener("abort", abortCombined, { once: true });
|
|
96
|
-
return {
|
|
97
|
-
signal: controller.signal,
|
|
98
|
-
cleanup: () => {
|
|
99
|
-
existing.removeEventListener("abort", abortCombined);
|
|
100
|
-
timeoutSignal.removeEventListener("abort", abortCombined);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function attachTimeoutSignal(ctx, timeoutSignal) {
|
|
105
|
-
if (!ctx || typeof ctx !== "object") {
|
|
106
|
-
return () => {
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
const target = ctx;
|
|
110
|
-
if (!("signal" in target)) {
|
|
111
|
-
return () => {
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
const previous = target.signal;
|
|
115
|
-
if (previous !== void 0 && !isAbortSignalLike(previous)) {
|
|
116
|
-
return () => {
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
let nextSignal = timeoutSignal;
|
|
120
|
-
let cleanupMerged = () => {
|
|
121
|
-
};
|
|
122
|
-
if (isAbortSignalLike(previous) && previous !== timeoutSignal) {
|
|
123
|
-
const merged = mergeAbortSignals(previous, timeoutSignal);
|
|
124
|
-
nextSignal = merged.signal;
|
|
125
|
-
cleanupMerged = merged.cleanup;
|
|
126
|
-
}
|
|
127
|
-
if (!canAssignSignal(target)) {
|
|
128
|
-
return cleanupMerged;
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
target.signal = nextSignal;
|
|
132
|
-
} catch {
|
|
133
|
-
cleanupMerged();
|
|
134
|
-
return () => {
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return () => {
|
|
138
|
-
cleanupMerged();
|
|
139
|
-
try {
|
|
140
|
-
if (previous === void 0) {
|
|
141
|
-
delete target.signal;
|
|
142
|
-
} else {
|
|
143
|
-
target.signal = previous;
|
|
144
|
-
}
|
|
145
|
-
} catch {
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function raceWithTimeout(task, ms, onTimeout) {
|
|
150
|
-
return new Promise((resolve, reject) => {
|
|
151
|
-
let settled = false;
|
|
152
|
-
const hasAbortTimeout = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function";
|
|
153
|
-
let signal;
|
|
154
|
-
let fallbackTimer;
|
|
155
|
-
function handleTimeout() {
|
|
156
|
-
if (!settled) {
|
|
157
|
-
settled = true;
|
|
158
|
-
onTimeout();
|
|
159
|
-
if (signal) {
|
|
160
|
-
signal.removeEventListener("abort", handleTimeout);
|
|
161
|
-
}
|
|
162
|
-
reject(new SpringMiddlewareError(`Middleware chain timed out after ${ms}ms`, "timeout"));
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
if (hasAbortTimeout) {
|
|
166
|
-
signal = AbortSignal.timeout(ms);
|
|
167
|
-
signal.addEventListener("abort", handleTimeout, { once: true });
|
|
168
|
-
} else {
|
|
169
|
-
fallbackTimer = setTimeout(handleTimeout, ms);
|
|
170
|
-
}
|
|
171
|
-
task.then(
|
|
172
|
-
() => {
|
|
173
|
-
if (!settled) {
|
|
174
|
-
settled = true;
|
|
175
|
-
if (fallbackTimer !== void 0) clearTimeout(fallbackTimer);
|
|
176
|
-
if (signal) signal.removeEventListener("abort", handleTimeout);
|
|
177
|
-
resolve();
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
(err) => {
|
|
181
|
-
if (!settled) {
|
|
182
|
-
settled = true;
|
|
183
|
-
if (fallbackTimer !== void 0) clearTimeout(fallbackTimer);
|
|
184
|
-
if (signal) signal.removeEventListener("abort", handleTimeout);
|
|
185
|
-
reject(err);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
);
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// src/middleware/middleware-registry.ts
|
|
193
|
-
var fallbackRegistry = /* @__PURE__ */ new Map();
|
|
194
|
-
registerFallbackMigration((instance) => {
|
|
195
|
-
if (fallbackRegistry.size === 0) return;
|
|
196
|
-
const target = instance.core.middlewareRegistry;
|
|
197
|
-
for (const [slot, entries] of fallbackRegistry) {
|
|
198
|
-
if (entries.length === 0) continue;
|
|
199
|
-
const existing = target.get(slot);
|
|
200
|
-
if (!existing) {
|
|
201
|
-
target.set(slot, [...entries]);
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
for (const entry of entries) {
|
|
205
|
-
if (!existing.includes(entry)) {
|
|
206
|
-
existing.push(entry);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
existing.sort((a, b) => b.priority - a.priority);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
function removeMiddlewareEntry(registry, slot, entry) {
|
|
213
|
-
const current = registry.get(slot);
|
|
214
|
-
if (!current) return;
|
|
215
|
-
const idx = current.indexOf(entry);
|
|
216
|
-
if (idx !== -1) current.splice(idx, 1);
|
|
217
|
-
}
|
|
218
|
-
function getRegistry() {
|
|
219
|
-
const instance = tryGetSpringInstance();
|
|
220
|
-
return instance ? instance.core.middlewareRegistry : fallbackRegistry;
|
|
221
|
-
}
|
|
222
|
-
function registerMiddleware(slot, middleware, options) {
|
|
223
|
-
if (!slot || typeof slot !== "string") {
|
|
224
|
-
devThrow("Middleware", "registerMiddleware(): slot must be a non-empty string");
|
|
225
|
-
return () => {
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
if (typeof middleware !== "function") {
|
|
229
|
-
devThrow("Middleware", `registerMiddleware("${slot}"): middleware must be a function`);
|
|
230
|
-
return () => {
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
const priority = options?.priority ?? 0;
|
|
234
|
-
const entry = { fn: middleware, priority };
|
|
235
|
-
const registry = getRegistry();
|
|
236
|
-
let list = registry.get(slot);
|
|
237
|
-
if (!list) {
|
|
238
|
-
list = [];
|
|
239
|
-
registry.set(slot, list);
|
|
240
|
-
}
|
|
241
|
-
list.push(entry);
|
|
242
|
-
list.sort((a, b) => b.priority - a.priority);
|
|
243
|
-
return () => {
|
|
244
|
-
const e = entry;
|
|
245
|
-
removeMiddlewareEntry(registry, slot, e);
|
|
246
|
-
if (registry !== fallbackRegistry) {
|
|
247
|
-
removeMiddlewareEntry(fallbackRegistry, slot, e);
|
|
248
|
-
}
|
|
249
|
-
const instance = tryGetSpringInstance();
|
|
250
|
-
if (instance) {
|
|
251
|
-
removeMiddlewareEntry(
|
|
252
|
-
instance.core.middlewareRegistry,
|
|
253
|
-
slot,
|
|
254
|
-
e
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
function getMiddlewareRunner(slot) {
|
|
260
|
-
const registry = getRegistry();
|
|
261
|
-
const entries = registry.get(slot);
|
|
262
|
-
if (!entries || entries.length === 0) {
|
|
263
|
-
return async () => {
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
return composeMiddleware(entries.map((e) => e.fn));
|
|
267
|
-
}
|
|
268
|
-
function getRegisteredMiddlewareSlots() {
|
|
269
|
-
const registry = getRegistry();
|
|
270
|
-
return Array.from(registry.entries()).filter(([, list]) => list.length > 0).map(([slot]) => slot);
|
|
271
|
-
}
|
|
272
|
-
function clearAllMiddleware() {
|
|
273
|
-
const registry = getRegistry();
|
|
274
|
-
registry.clear();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
export {
|
|
278
|
-
composeMiddleware,
|
|
279
|
-
registerMiddleware,
|
|
280
|
-
getMiddlewareRunner,
|
|
281
|
-
getRegisteredMiddlewareSlots,
|
|
282
|
-
clearAllMiddleware
|
|
283
|
-
};
|
|
284
|
-
//# sourceMappingURL=chunk-MEWPYTWC.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware/middleware-runner.ts","../src/middleware/middleware-registry.ts"],"sourcesContent":["/**\n * Koa-style middleware composition.\n * Chains middleware functions with a `next()` pattern.\n * @module middleware-runner\n */\n\nimport { SpringMiddlewareError } from \"../errors/errors\";\nimport type { MiddlewareFn } from \"./middleware-types\";\n\nexport interface ComposeOptions {\n /**\n * Optional timeout in milliseconds for the entire middleware chain.\n * If the chain doesn't complete within this time, a SpringMiddlewareError is thrown.\n * When omitted, no timeout is applied (backward-compatible default).\n */\n timeoutMs?: number;\n}\n\n/**\n * Compose an array of middleware functions into a single function.\n * Each middleware receives a context and a `next` callback.\n * Calling `next()` invokes the next middleware in the chain.\n * Calling `next()` more than once throws an error.\n *\n * @param middlewares - Array of middleware functions to compose\n * @param options - Optional configuration (e.g. timeout)\n * @returns A function that runs the full middleware chain on a given context.\n */\nexport function composeMiddleware<TContext>(\n middlewares: ReadonlyArray<MiddlewareFn<TContext>>,\n options?: ComposeOptions,\n): (ctx: TContext) => Promise<void> {\n const timeoutMs = options?.timeoutMs;\n\n return async (ctx: TContext): Promise<void> => {\n let index = -1;\n let timedOut = false;\n const timeoutController =\n timeoutMs != null && timeoutMs > 0 && typeof AbortController !== \"undefined\"\n ? new AbortController()\n : null;\n const restoreSignal = timeoutController ? attachTimeoutSignal(ctx, timeoutController.signal) : () => {};\n\n const createTimeoutError = (): SpringMiddlewareError =>\n new SpringMiddlewareError(\n `Middleware chain timed out after ${timeoutMs}ms`,\n \"timeout\",\n );\n\n async function dispatch(i: number): Promise<void> {\n if (timedOut) {\n throw createTimeoutError();\n }\n if (i <= index) {\n throw new SpringMiddlewareError(\"next() called multiple times in middleware.\", \"compose\");\n }\n index = i;\n if (i >= middlewares.length) {\n return;\n }\n const fn = middlewares[i];\n if (!fn) return;\n await fn(ctx, () => dispatch(i + 1));\n }\n\n try {\n if (timeoutMs != null && timeoutMs > 0) {\n await raceWithTimeout(dispatch(0), timeoutMs, () => {\n timedOut = true;\n timeoutController?.abort();\n });\n } else {\n await dispatch(0);\n }\n } finally {\n restoreSignal();\n }\n };\n}\n\nfunction isAbortSignalLike(value: unknown): value is AbortSignal {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as { aborted?: unknown; addEventListener?: unknown };\n return typeof candidate.aborted === \"boolean\" && typeof candidate.addEventListener === \"function\";\n}\n\nfunction canAssignSignal(target: Record<string, unknown>): boolean {\n let current: object | null = target;\n while (current) {\n const descriptor = Object.getOwnPropertyDescriptor(current, \"signal\");\n if (!descriptor) {\n current = Object.getPrototypeOf(current);\n continue;\n }\n if (\"set\" in descriptor) {\n return typeof descriptor.set === \"function\";\n }\n return descriptor.writable === true;\n }\n return true;\n}\n\nfunction mergeAbortSignals(\n existing: AbortSignal,\n timeoutSignal: AbortSignal,\n): { signal: AbortSignal; cleanup: () => void } {\n if (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.any === \"function\") {\n return { signal: AbortSignal.any([existing, timeoutSignal]), cleanup: () => {} };\n }\n\n if (typeof AbortController === \"undefined\") {\n return { signal: timeoutSignal, cleanup: () => {} };\n }\n\n const controller = new AbortController();\n const abortCombined = (): void => {\n if (!controller.signal.aborted) {\n controller.abort();\n }\n };\n\n if (existing.aborted || timeoutSignal.aborted) {\n abortCombined();\n return { signal: controller.signal, cleanup: () => {} };\n }\n\n existing.addEventListener(\"abort\", abortCombined, { once: true });\n timeoutSignal.addEventListener(\"abort\", abortCombined, { once: true });\n\n return {\n signal: controller.signal,\n cleanup: () => {\n existing.removeEventListener(\"abort\", abortCombined);\n timeoutSignal.removeEventListener(\"abort\", abortCombined);\n },\n };\n}\n\n/**\n * If the context exposes a `signal` field, attach timeout signal so middleware\n * can abort downstream fetch/IO operations cooperatively.\n */\nfunction attachTimeoutSignal<TContext>(ctx: TContext, timeoutSignal: AbortSignal): () => void {\n if (!ctx || typeof ctx !== \"object\") {\n return () => {};\n }\n\n const target = ctx as Record<string, unknown>;\n if (!(\"signal\" in target)) {\n return () => {};\n }\n\n const previous = target.signal;\n if (previous !== undefined && !isAbortSignalLike(previous)) {\n return () => {};\n }\n\n let nextSignal: AbortSignal = timeoutSignal;\n let cleanupMerged = () => {};\n if (\n isAbortSignalLike(previous) &&\n previous !== timeoutSignal\n ) {\n const merged = mergeAbortSignals(previous, timeoutSignal);\n nextSignal = merged.signal;\n cleanupMerged = merged.cleanup;\n }\n\n if (!canAssignSignal(target)) {\n return cleanupMerged;\n }\n\n try {\n target.signal = nextSignal;\n } catch {\n cleanupMerged();\n return () => {};\n }\n\n return () => {\n cleanupMerged();\n try {\n if (previous === undefined) {\n delete target.signal;\n } else {\n target.signal = previous;\n }\n } catch {\n // Ignore restore errors for read-only or sealed contexts.\n }\n };\n}\n\n/**\n * Race a promise against a timeout. Rejects with SpringMiddlewareError if the\n * timeout fires first. Uses AbortSignal.timeout where available, falling\n * back to setTimeout for older runtimes.\n */\nfunction raceWithTimeout(task: Promise<void>, ms: number, onTimeout: () => void): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n // Use AbortSignal.timeout if available (Node 18+, modern browsers)\n const hasAbortTimeout = typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\";\n let signal: AbortSignal | undefined;\n let fallbackTimer: ReturnType<typeof setTimeout> | undefined;\n\n function handleTimeout(): void {\n if (!settled) {\n settled = true;\n onTimeout();\n if (signal) {\n signal.removeEventListener(\"abort\", handleTimeout);\n }\n reject(new SpringMiddlewareError(`Middleware chain timed out after ${ms}ms`, \"timeout\"));\n }\n }\n\n if (hasAbortTimeout) {\n signal = AbortSignal.timeout(ms);\n signal.addEventListener(\"abort\", handleTimeout, { once: true });\n } else {\n fallbackTimer = setTimeout(handleTimeout, ms);\n }\n\n task.then(\n () => {\n if (!settled) {\n settled = true;\n if (fallbackTimer !== undefined) clearTimeout(fallbackTimer);\n if (signal) signal.removeEventListener(\"abort\", handleTimeout);\n resolve();\n }\n },\n (err: unknown) => {\n if (!settled) {\n settled = true;\n if (fallbackTimer !== undefined) clearTimeout(fallbackTimer);\n if (signal) signal.removeEventListener(\"abort\", handleTimeout);\n reject(err);\n }\n },\n );\n });\n}\n","/**\n * Middleware registry — manages middleware functions registered per slot.\n *\n * Type-safe: the context type is inferred from the slot name via MiddlewareSlotMap.\n * Custom slots added via declaration merging also get full type inference.\n *\n * @module middleware-registry\n */\n\nimport { tryGetSpringInstance } from \"../instance/current-instance\";\nimport { registerFallbackMigration } from \"../instance/fallback-bridge\";\nimport { devThrow } from \"../utils/dev-warnings\";\nimport { composeMiddleware } from \"./middleware-runner\";\nimport type { MiddlewareEntry, MiddlewareFn, MiddlewareSlot } from \"./middleware-types\";\n\nexport interface MiddlewareOptions {\n /** Higher priority middleware runs first. Default: 0 */\n priority?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- heterogeneous registry stores middlewares for multiple context types by slot\nconst fallbackRegistry = new Map<MiddlewareSlot, MiddlewareEntry<any>[]>();\n\n// Migrate pre-mount middleware registrations to SpringInstance when it becomes available.\nregisterFallbackMigration((instance) => {\n if (fallbackRegistry.size === 0) return;\n\n const target = instance.core.middlewareRegistry;\n for (const [slot, entries] of fallbackRegistry) {\n if (entries.length === 0) continue;\n const existing = target.get(slot);\n if (!existing) {\n target.set(slot, [...entries]);\n continue;\n }\n for (const entry of entries) {\n if (!existing.includes(entry)) {\n existing.push(entry);\n }\n }\n existing.sort((a, b) => b.priority - a.priority);\n }\n});\n\nfunction removeMiddlewareEntry(\n registry: Map<MiddlewareSlot, MiddlewareEntry<unknown>[]>,\n slot: MiddlewareSlot,\n entry: MiddlewareEntry<unknown>,\n): void {\n const current = registry.get(slot);\n if (!current) return;\n const idx = current.indexOf(entry);\n if (idx !== -1) current.splice(idx, 1);\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- same rationale as fallbackRegistry; runtime slot dispatch preserves context typing at call sites\nfunction getRegistry(): Map<MiddlewareSlot, MiddlewareEntry<any>[]> {\n const instance = tryGetSpringInstance();\n return instance ? instance.core.middlewareRegistry : fallbackRegistry;\n}\n\n/**\n * Register a middleware function for a given slot.\n * The context type is automatically inferred from the slot name via MiddlewareSlotMap.\n *\n * @example\n * ```ts\n * // Context type is inferred as FormSaveContext\n * const unregister = registerMiddleware(\"form:beforeSave\", async (ctx, next) => {\n * console.log(\"Saving entity:\", ctx.entity);\n * await next();\n * });\n * unregister(); // Cleanup when no longer needed\n *\n * // With priority (higher = runs first):\n * registerMiddleware(\"form:beforeSave\", auditMiddleware, { priority: 10 });\n * ```\n *\n * @param slot - Middleware slot name (e.g. \"form:beforeSave\", \"api:beforeRequest\")\n * @param middleware - Koa-style middleware function receiving `(ctx, next)`\n * @param options - Optional settings; `priority` controls execution order (higher runs first, default 0)\n * @returns An unregister function that removes this middleware from the slot.\n */\nexport function registerMiddleware<TContext = unknown>(\n slot: MiddlewareSlot,\n middleware: MiddlewareFn<TContext>,\n options?: MiddlewareOptions,\n): () => void {\n if (!slot || typeof slot !== \"string\") {\n devThrow(\"Middleware\", \"registerMiddleware(): slot must be a non-empty string\");\n return () => {};\n }\n if (typeof middleware !== \"function\") {\n devThrow(\"Middleware\", `registerMiddleware(\"${slot}\"): middleware must be a function`);\n return () => {};\n }\n\n const priority = options?.priority ?? 0;\n const entry: MiddlewareEntry<TContext> = { fn: middleware, priority };\n\n const registry = getRegistry();\n let list = registry.get(slot);\n if (!list) {\n list = [];\n registry.set(slot, list);\n }\n list.push(entry);\n // Stable sort: higher priority first\n list.sort((a, b) => b.priority - a.priority);\n\n return () => {\n const e = entry as MiddlewareEntry<unknown>;\n removeMiddlewareEntry(registry as Map<MiddlewareSlot, MiddlewareEntry<unknown>[]>, slot, e);\n if (registry !== fallbackRegistry) {\n removeMiddlewareEntry(fallbackRegistry as Map<MiddlewareSlot, MiddlewareEntry<unknown>[]>, slot, e);\n }\n const instance = tryGetSpringInstance();\n if (instance) {\n removeMiddlewareEntry(\n instance.core.middlewareRegistry as Map<MiddlewareSlot, MiddlewareEntry<unknown>[]>,\n slot,\n e,\n );\n }\n };\n}\n\n/**\n * Get a composed runner for a given slot.\n * Returns a function that executes all registered middleware for that slot\n * in priority order (higher priority first) using the Koa-style `next()` pattern.\n *\n * If no middleware is registered for the slot, the returned function is a no-op.\n *\n * @param slot - Middleware slot name to compose a runner for\n * @returns An async function that runs all middleware for the slot on a given context.\n */\nexport function getMiddlewareRunner<TContext = unknown>(\n slot: MiddlewareSlot,\n): (ctx: TContext) => Promise<void> {\n const registry = getRegistry();\n const entries = registry.get(slot);\n if (!entries || entries.length === 0) {\n return async () => {};\n }\n return composeMiddleware<TContext>(entries.map((e) => e.fn as MiddlewareFn<TContext>));\n}\n\n/**\n * Get all slot names that have at least one middleware registered.\n * Useful for debugging and introspection.\n */\nexport function getRegisteredMiddlewareSlots(): MiddlewareSlot[] {\n const registry = getRegistry();\n return Array.from(registry.entries())\n .filter(([, list]) => list.length > 0)\n .map(([slot]) => slot);\n}\n\n/**\n * Remove all registered middleware. Intended for testing.\n */\nexport function clearAllMiddleware(): void {\n const registry = getRegistry();\n registry.clear();\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-N2L4TUC4.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// src/i18n/default-messages.ts
|
|
2
|
-
var DEFAULT_MESSAGES = {
|
|
3
|
-
"admin-fill-value": "This field is required",
|
|
4
|
-
"admin-invalid-phone-number-format": "Invalid phone number format",
|
|
5
|
-
"admin-invalid-email-format": "Invalid email format",
|
|
6
|
-
"admin-email-contains-multiple-addresses": "Field contains multiple email addresses",
|
|
7
|
-
"admin-invalid-url-format": "Invalid URL format",
|
|
8
|
-
"admin-password-min-length": "Password must be at least 8 characters",
|
|
9
|
-
"admin-password-uppercase": "Password must contain an uppercase letter",
|
|
10
|
-
"admin-password-lowercase": "Password must contain a lowercase letter",
|
|
11
|
-
"admin-password-digit": "Password must contain a digit",
|
|
12
|
-
"admin-password-special-char": "Password must contain a special character",
|
|
13
|
-
"admin-yes": "Yes",
|
|
14
|
-
"admin-no": "No",
|
|
15
|
-
"admin-login-failed": "Login failed",
|
|
16
|
-
"admin-session-expired": "Session expired. Please log in again.",
|
|
17
|
-
"admin-fill-all-required-fields": "Please fill in all required fields",
|
|
18
|
-
"admin-username": "Username",
|
|
19
|
-
"admin-detail": "Detail",
|
|
20
|
-
"admin-not-found": "Not found",
|
|
21
|
-
"admin-unknown-error": "Unknown error",
|
|
22
|
-
"admin-validation-error": "Validation error",
|
|
23
|
-
"admin-sorted-ascending": "Sorted ascending",
|
|
24
|
-
"admin-sorted-descending": "Sorted descending",
|
|
25
|
-
"admin-sort-cleared": "Sort cleared",
|
|
26
|
-
"admin-of": "of",
|
|
27
|
-
"admin-rows-selected": "rows selected",
|
|
28
|
-
"admin-tree": "Tree"
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
DEFAULT_MESSAGES
|
|
33
|
-
};
|
|
34
|
-
//# sourceMappingURL=chunk-N2L4TUC4.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/i18n/default-messages.ts"],"sourcesContent":["/**\n * Built-in default messages for framework UI strings.\n * These provide a working default so the framework operates out of the box\n * without requiring a ContentAdapter for basic validation messages.\n * Consumers can override via setContentAdapter() for full i18n.\n * @module default-messages\n */\n\nexport const DEFAULT_MESSAGES = {\n \"admin-fill-value\": \"This field is required\",\n \"admin-invalid-phone-number-format\": \"Invalid phone number format\",\n \"admin-invalid-email-format\": \"Invalid email format\",\n \"admin-email-contains-multiple-addresses\": \"Field contains multiple email addresses\",\n \"admin-invalid-url-format\": \"Invalid URL format\",\n \"admin-password-min-length\": \"Password must be at least 8 characters\",\n \"admin-password-uppercase\": \"Password must contain an uppercase letter\",\n \"admin-password-lowercase\": \"Password must contain a lowercase letter\",\n \"admin-password-digit\": \"Password must contain a digit\",\n \"admin-password-special-char\": \"Password must contain a special character\",\n \"admin-yes\": \"Yes\",\n \"admin-no\": \"No\",\n \"admin-login-failed\": \"Login failed\",\n \"admin-session-expired\": \"Session expired. Please log in again.\",\n \"admin-fill-all-required-fields\": \"Please fill in all required fields\",\n \"admin-username\": \"Username\",\n \"admin-detail\": \"Detail\",\n \"admin-not-found\": \"Not found\",\n \"admin-unknown-error\": \"Unknown error\",\n \"admin-validation-error\": \"Validation error\",\n \"admin-sorted-ascending\": \"Sorted ascending\",\n \"admin-sorted-descending\": \"Sorted descending\",\n \"admin-sort-cleared\": \"Sort cleared\",\n \"admin-of\": \"of\",\n \"admin-rows-selected\": \"rows selected\",\n \"admin-tree\": \"Tree\",\n} as const satisfies Record<string, string>;\n"],"mappings":";AAQO,IAAM,mBAAmB;AAAA,EAC5B,oBAAoB;AAAA,EACpB,qCAAqC;AAAA,EACrC,8BAA8B;AAAA,EAC9B,2CAA2C;AAAA,EAC3C,4BAA4B;AAAA,EAC5B,6BAA6B;AAAA,EAC7B,4BAA4B;AAAA,EAC5B,4BAA4B;AAAA,EAC5B,wBAAwB;AAAA,EACxB,+BAA+B;AAAA,EAC/B,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,kCAAkC;AAAA,EAClC,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,0BAA0B;AAAA,EAC1B,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA,EAC3B,sBAAsB;AAAA,EACtB,YAAY;AAAA,EACZ,uBAAuB;AAAA,EACvB,cAAc;AAClB;","names":[]}
|
package/dist/chunk-NQQIVCLX.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_MESSAGES
|
|
3
|
-
} from "./chunk-N2L4TUC4.js";
|
|
4
|
-
import {
|
|
5
|
-
registerFallbackMigration
|
|
6
|
-
} from "./chunk-RUCXSQEY.js";
|
|
7
|
-
import {
|
|
8
|
-
tryGetSpringInstance
|
|
9
|
-
} from "./chunk-EFUBAQCV.js";
|
|
10
|
-
|
|
11
|
-
// src/adapters/content-adapter.ts
|
|
12
|
-
var fallback = {
|
|
13
|
-
getRes: (key) => DEFAULT_MESSAGES[key] ?? `[${key}]`
|
|
14
|
-
};
|
|
15
|
-
function setContentAdapter(adapter) {
|
|
16
|
-
const instance = tryGetSpringInstance();
|
|
17
|
-
if (instance) {
|
|
18
|
-
instance.core.contentAdapter = adapter;
|
|
19
|
-
} else {
|
|
20
|
-
fallbackAdapter = adapter;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
var fallbackAdapter = fallback;
|
|
24
|
-
registerFallbackMigration((instance) => {
|
|
25
|
-
if (fallbackAdapter !== fallback) {
|
|
26
|
-
instance.core.contentAdapter = fallbackAdapter;
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
function getContentRes(key) {
|
|
30
|
-
const instance = tryGetSpringInstance();
|
|
31
|
-
const adapter = instance ? instance.core.contentAdapter : fallbackAdapter;
|
|
32
|
-
return adapter.getRes(key);
|
|
33
|
-
}
|
|
34
|
-
function clearContentAdapter() {
|
|
35
|
-
const instance = tryGetSpringInstance();
|
|
36
|
-
if (instance) {
|
|
37
|
-
instance.core.contentAdapter = fallback;
|
|
38
|
-
}
|
|
39
|
-
fallbackAdapter = fallback;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export {
|
|
43
|
-
setContentAdapter,
|
|
44
|
-
getContentRes,
|
|
45
|
-
clearContentAdapter
|
|
46
|
-
};
|
|
47
|
-
//# sourceMappingURL=chunk-NQQIVCLX.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/content-adapter.ts"],"sourcesContent":["/**\n * Content adapter — decouples API/validation layers from the i18n system (contents store).\n * Pattern matches setLogAdapter() in logger.ts.\n * @module content-adapter\n */\n\nimport { DEFAULT_MESSAGES } from \"../i18n/default-messages\";\nimport { tryGetSpringInstance } from \"../instance/current-instance\";\nimport { registerFallbackMigration } from \"../instance/fallback-bridge\";\n\nexport interface ContentAdapter {\n getRes(key: string): string;\n}\n\nconst fallback = {\n getRes: (key) => (DEFAULT_MESSAGES as Record<string, string>)[key] ?? `[${key}]`,\n} satisfies ContentAdapter;\n\nexport function setContentAdapter(adapter: ContentAdapter): void {\n const instance = tryGetSpringInstance();\n if (instance) {\n instance.core.contentAdapter = adapter;\n } else {\n fallbackAdapter = adapter;\n }\n}\n\n// Fallback for code that runs before SpringInstance is created\nlet fallbackAdapter: ContentAdapter = fallback;\n\n// Migrate fallback content adapter to SpringInstance when SpringProvider mounts\nregisterFallbackMigration((instance) => {\n if (fallbackAdapter !== fallback) {\n instance.core.contentAdapter = fallbackAdapter;\n }\n});\n\n/** Returns translated content via the registered adapter. Replaces direct getRes() imports in core/api layers. */\nexport function getContentRes(key: string): string {\n const instance = tryGetSpringInstance();\n const adapter = instance ? instance.core.contentAdapter : fallbackAdapter;\n return adapter.getRes(key);\n}\n\n/** Reset to default content adapter. For testing/integration teardown only. */\nexport function clearContentAdapter(): void {\n const instance = tryGetSpringInstance();\n if (instance) {\n instance.core.contentAdapter = fallback;\n }\n fallbackAdapter = fallback;\n}\n"],"mappings":";;;;;;;;;;;AAcA,IAAM,WAAW;AAAA,EACb,QAAQ,CAAC,QAAS,iBAA4C,GAAG,KAAK,IAAI,GAAG;AACjF;AAEO,SAAS,kBAAkB,SAA+B;AAC7D,QAAM,WAAW,qBAAqB;AACtC,MAAI,UAAU;AACV,aAAS,KAAK,iBAAiB;AAAA,EACnC,OAAO;AACH,sBAAkB;AAAA,EACtB;AACJ;AAGA,IAAI,kBAAkC;AAGtC,0BAA0B,CAAC,aAAa;AACpC,MAAI,oBAAoB,UAAU;AAC9B,aAAS,KAAK,iBAAiB;AAAA,EACnC;AACJ,CAAC;AAGM,SAAS,cAAc,KAAqB;AAC/C,QAAM,WAAW,qBAAqB;AACtC,QAAM,UAAU,WAAW,SAAS,KAAK,iBAAiB;AAC1D,SAAO,QAAQ,OAAO,GAAG;AAC7B;AAGO,SAAS,sBAA4B;AACxC,QAAM,WAAW,qBAAqB;AACtC,MAAI,UAAU;AACV,aAAS,KAAK,iBAAiB;AAAA,EACnC;AACA,oBAAkB;AACtB;","names":[]}
|