@spring-systems/core 0.8.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/CHANGELOG.md +33 -0
- package/LICENSE +8 -0
- package/README.md +77 -0
- package/dist/adapters/index.d.ts +246 -0
- package/dist/adapters/index.js +56 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/auth/index.d.ts +17 -0
- package/dist/auth/index.js +19 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/chunk-5D6XE7NJ.js +16 -0
- package/dist/chunk-5D6XE7NJ.js.map +1 -0
- package/dist/chunk-EFUBAQCV.js +94 -0
- package/dist/chunk-EFUBAQCV.js.map +1 -0
- package/dist/chunk-F2SIMWZ5.js +173 -0
- package/dist/chunk-F2SIMWZ5.js.map +1 -0
- package/dist/chunk-F7WUQJH7.js +399 -0
- package/dist/chunk-F7WUQJH7.js.map +1 -0
- package/dist/chunk-GON7Q32Q.js +176 -0
- package/dist/chunk-GON7Q32Q.js.map +1 -0
- package/dist/chunk-GXU75LQX.js +182 -0
- package/dist/chunk-GXU75LQX.js.map +1 -0
- package/dist/chunk-HFELOXDQ.js +110 -0
- package/dist/chunk-HFELOXDQ.js.map +1 -0
- package/dist/chunk-KX32MU3I.js +190 -0
- package/dist/chunk-KX32MU3I.js.map +1 -0
- package/dist/chunk-MEWPYTWC.js +284 -0
- package/dist/chunk-MEWPYTWC.js.map +1 -0
- package/dist/chunk-N2L4TUC4.js +34 -0
- package/dist/chunk-N2L4TUC4.js.map +1 -0
- package/dist/chunk-NQQIVCLX.js +47 -0
- package/dist/chunk-NQQIVCLX.js.map +1 -0
- package/dist/chunk-OSSX443T.js +146 -0
- package/dist/chunk-OSSX443T.js.map +1 -0
- package/dist/chunk-PT4DIYUK.js +78 -0
- package/dist/chunk-PT4DIYUK.js.map +1 -0
- package/dist/chunk-QAVWXARR.js +51 -0
- package/dist/chunk-QAVWXARR.js.map +1 -0
- package/dist/chunk-RRWKDFAB.js +143 -0
- package/dist/chunk-RRWKDFAB.js.map +1 -0
- package/dist/chunk-RUCXSQEY.js +42 -0
- package/dist/chunk-RUCXSQEY.js.map +1 -0
- package/dist/chunk-S6RPCN5H.js +64 -0
- package/dist/chunk-S6RPCN5H.js.map +1 -0
- package/dist/chunk-S7MKRNMI.js +153 -0
- package/dist/chunk-S7MKRNMI.js.map +1 -0
- package/dist/chunk-SQB4F3EF.js +55 -0
- package/dist/chunk-SQB4F3EF.js.map +1 -0
- package/dist/chunk-U5OH3GAI.js +399 -0
- package/dist/chunk-U5OH3GAI.js.map +1 -0
- package/dist/chunk-UDT2RPX2.js +43 -0
- package/dist/chunk-UDT2RPX2.js.map +1 -0
- package/dist/config/index.d.ts +63 -0
- package/dist/config/index.js +109 -0
- package/dist/config/index.js.map +1 -0
- package/dist/devtools/index.d.ts +54 -0
- package/dist/devtools/index.js +67 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/errors/index.d.ts +39 -0
- package/dist/errors/index.js +21 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/events/index.d.ts +153 -0
- package/dist/events/index.js +12 -0
- package/dist/events/index.js.map +1 -0
- package/dist/form-types-D3MdGpjA.d.ts +290 -0
- package/dist/framework-config-types-DeUbx4bu.d.ts +574 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/i18n/index.js +7 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/instance/index.d.ts +112 -0
- package/dist/instance/index.js +37 -0
- package/dist/instance/index.js.map +1 -0
- package/dist/logger/index.d.ts +44 -0
- package/dist/logger/index.js +27 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/middleware/index.d.ts +91 -0
- package/dist/middleware/index.js +23 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware-registry-DT002qRd.d.ts +60 -0
- package/dist/middleware-types-DVG9C1qJ.d.ts +85 -0
- package/dist/plugins/index.d.ts +104 -0
- package/dist/plugins/index.js +16 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/runtime-env-config-CajOEJCP.d.ts +148 -0
- package/dist/security-sanitize-Bb0PExM6.d.ts +9 -0
- package/dist/spring-instance-EbUh4mQb.d.ts +119 -0
- package/dist/testing/index.d.ts +129 -0
- package/dist/testing/index.js +171 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types/index.d.ts +85 -0
- package/dist/types/index.js +72 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +143 -0
- package/dist/utils/index.js +786 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/validation/index.d.ts +48 -0
- package/dist/validation/index.js +147 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +142 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { F as FrameworkConfigOverrides } from '../framework-config-types-DeUbx4bu.js';
|
|
2
|
+
import { d as SpringInstance } from '../spring-instance-EbUh4mQb.js';
|
|
3
|
+
export { H as HandlerEntry, I as InstanceContentAdapter, e as InstanceLifecycleState, c as InstanceLogAdapter, b as InstanceNotificationAdapter, L as LogoutHandler, a as LogoutReason, R as RequestHook, f as ResponseHook, S as SecurityEventType, g as SpringApiState, h as SpringCoreState, i as SpringUIState } from '../spring-instance-EbUh4mQb.js';
|
|
4
|
+
import '../middleware-types-DVG9C1qJ.js';
|
|
5
|
+
import '../form-types-D3MdGpjA.js';
|
|
6
|
+
import '../security-sanitize-Bb0PExM6.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Factory for creating SpringInstance — a clean state container with all defaults.
|
|
10
|
+
*
|
|
11
|
+
* Lifecycle: `creating` → `ready` → `disposing` → `disposed`
|
|
12
|
+
*
|
|
13
|
+
* @module create-instance
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a fresh SpringInstance with clean state.
|
|
18
|
+
* Each instance gets its own event listeners, middleware registry, validators, etc.
|
|
19
|
+
*
|
|
20
|
+
* The instance starts in `creating` state. Call `markInstanceReady()` after
|
|
21
|
+
* applying plugins and fallbacks to transition to `ready`.
|
|
22
|
+
*
|
|
23
|
+
* @param overrides - Partial config overrides merged with DEFAULT_FRAMEWORK_CONFIG (deep-merged per section)
|
|
24
|
+
* @returns A new SpringInstance in `creating` lifecycle state with a unique ID.
|
|
25
|
+
*/
|
|
26
|
+
declare function createSpringInstance(overrides?: FrameworkConfigOverrides): SpringInstance;
|
|
27
|
+
/**
|
|
28
|
+
* Transition an instance to `ready` state.
|
|
29
|
+
* Should be called after all initialization (plugins, fallbacks, adapters) is complete.
|
|
30
|
+
*/
|
|
31
|
+
declare function markInstanceReady(instance: SpringInstance): void;
|
|
32
|
+
/**
|
|
33
|
+
* Run one-time activation work for an instance and transition it to `ready`.
|
|
34
|
+
*
|
|
35
|
+
* Safe under StrictMode and remounts:
|
|
36
|
+
* - render phase may create the instance, but activation happens later
|
|
37
|
+
* - repeated activation on the same ready instance is a no-op
|
|
38
|
+
* - bootstrap failures clear the current-instance bridge before rethrowing
|
|
39
|
+
*/
|
|
40
|
+
declare function bootstrapSpringInstance(instance: SpringInstance, activate: () => void): void;
|
|
41
|
+
/**
|
|
42
|
+
* Check if an instance is in a usable state (creating or ready).
|
|
43
|
+
*/
|
|
44
|
+
declare function isInstanceActive(instance: SpringInstance): boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Current instance bridge — the one remaining singleton.
|
|
48
|
+
* Imperative code (API calls, middleware, etc.) reads from getSpringInstance().
|
|
49
|
+
* The SpringProvider in ui sets this via setSpringInstance().
|
|
50
|
+
*
|
|
51
|
+
* **SSR safety note:** This module uses a module-level variable, which means
|
|
52
|
+
* concurrent SSR requests in the same Node.js process will share the same
|
|
53
|
+
* instance. For multi-tenant SSR, use React Context instead of getSpringInstance().
|
|
54
|
+
*
|
|
55
|
+
* @module current-instance
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Set the current SpringInstance. Called once by SpringProvider on mount.
|
|
60
|
+
* Warns if replacing an active (non-disposed) instance — this indicates
|
|
61
|
+
* either multiple SpringProviders or missing cleanup.
|
|
62
|
+
*/
|
|
63
|
+
declare function setSpringInstance(instance: SpringInstance): void;
|
|
64
|
+
/**
|
|
65
|
+
* Get the current SpringInstance. Throws if not set.
|
|
66
|
+
* Use this in imperative code that requires a live instance.
|
|
67
|
+
*/
|
|
68
|
+
declare function getSpringInstance(): SpringInstance;
|
|
69
|
+
/**
|
|
70
|
+
* Get the current SpringInstance or null if not yet initialized.
|
|
71
|
+
* Use this in code that may run before SpringProvider mounts (e.g. config setup).
|
|
72
|
+
*/
|
|
73
|
+
declare function tryGetSpringInstance(): SpringInstance | null;
|
|
74
|
+
/**
|
|
75
|
+
* Clear the current instance. For testing and cleanup only.
|
|
76
|
+
*/
|
|
77
|
+
declare function clearSpringInstance(): void;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Centralized fallback bridge — migrates pre-mount state to a SpringInstance.
|
|
81
|
+
*
|
|
82
|
+
* Before SpringProvider mounts, various modules (config, adapters, event bus,
|
|
83
|
+
* middleware) store state in module-level fallback variables. When SpringProvider
|
|
84
|
+
* creates and sets the SpringInstance, this function migrates all fallback state
|
|
85
|
+
* to the instance in a single call.
|
|
86
|
+
*
|
|
87
|
+
* This replaces the previous pattern where each module independently checked
|
|
88
|
+
* tryGetSpringInstance() and maintained its own fallback state.
|
|
89
|
+
*
|
|
90
|
+
* @module fallback-bridge
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Migrate all pre-mount fallback state into the given SpringInstance.
|
|
95
|
+
* Called once by SpringProvider after instance creation.
|
|
96
|
+
*
|
|
97
|
+
* Modules register their fallback migration via registerFallbackMigration().
|
|
98
|
+
* This allows packages (ui, api) to register their own migrations
|
|
99
|
+
* without core needing to know about them.
|
|
100
|
+
*/
|
|
101
|
+
declare function applyAllFallbacks(instance: SpringInstance): void;
|
|
102
|
+
type FallbackMigration = (instance: SpringInstance) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Register a fallback migration function.
|
|
105
|
+
* Called by modules that maintain pre-mount fallback state (adapters, event bus, etc.)
|
|
106
|
+
* to ensure their state is migrated when SpringProvider mounts.
|
|
107
|
+
*/
|
|
108
|
+
declare function registerFallbackMigration(migration: FallbackMigration, priority?: number): void;
|
|
109
|
+
/** Clear all registered migrations. For testing only. */
|
|
110
|
+
declare function clearFallbackMigrations(): void;
|
|
111
|
+
|
|
112
|
+
export { SpringInstance, applyAllFallbacks, bootstrapSpringInstance, clearFallbackMigrations, clearSpringInstance, createSpringInstance, getSpringInstance, isInstanceActive, markInstanceReady, registerFallbackMigration, setSpringInstance, tryGetSpringInstance };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bootstrapSpringInstance,
|
|
3
|
+
createSpringInstance,
|
|
4
|
+
isInstanceActive,
|
|
5
|
+
markInstanceReady
|
|
6
|
+
} from "../chunk-F2SIMWZ5.js";
|
|
7
|
+
import "../chunk-GXU75LQX.js";
|
|
8
|
+
import "../chunk-S7MKRNMI.js";
|
|
9
|
+
import "../chunk-F7WUQJH7.js";
|
|
10
|
+
import "../chunk-N2L4TUC4.js";
|
|
11
|
+
import {
|
|
12
|
+
applyAllFallbacks,
|
|
13
|
+
clearFallbackMigrations,
|
|
14
|
+
registerFallbackMigration
|
|
15
|
+
} from "../chunk-RUCXSQEY.js";
|
|
16
|
+
import "../chunk-KX32MU3I.js";
|
|
17
|
+
import {
|
|
18
|
+
clearSpringInstance,
|
|
19
|
+
getSpringInstance,
|
|
20
|
+
setSpringInstance,
|
|
21
|
+
tryGetSpringInstance
|
|
22
|
+
} from "../chunk-EFUBAQCV.js";
|
|
23
|
+
import "../chunk-PT4DIYUK.js";
|
|
24
|
+
export {
|
|
25
|
+
applyAllFallbacks,
|
|
26
|
+
bootstrapSpringInstance,
|
|
27
|
+
clearFallbackMigrations,
|
|
28
|
+
clearSpringInstance,
|
|
29
|
+
createSpringInstance,
|
|
30
|
+
getSpringInstance,
|
|
31
|
+
isInstanceActive,
|
|
32
|
+
markInstanceReady,
|
|
33
|
+
registerFallbackMigration,
|
|
34
|
+
setSpringInstance,
|
|
35
|
+
tryGetSpringInstance
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { S as SecurityEventType } from '../spring-instance-EbUh4mQb.js';
|
|
2
|
+
import { S as SecurityLogData } from '../security-sanitize-Bb0PExM6.js';
|
|
3
|
+
import '../framework-config-types-DeUbx4bu.js';
|
|
4
|
+
import '../middleware-types-DVG9C1qJ.js';
|
|
5
|
+
import '../form-types-D3MdGpjA.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Console wrapper with timestamp and configurable log levels.
|
|
9
|
+
* @module logger
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
13
|
+
type BivariantCallback<TArgs extends unknown[], TResult = void> = {
|
|
14
|
+
bivarianceHack: (...args: TArgs) => TResult;
|
|
15
|
+
}["bivarianceHack"];
|
|
16
|
+
interface LogAdapter {
|
|
17
|
+
onError?: (context: string, error?: unknown) => void;
|
|
18
|
+
onWarn?: (context: string, message?: string) => void;
|
|
19
|
+
onSecurityEvent?: BivariantCallback<[event: SecurityEventType, data?: SecurityLogData]>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Set the minimum log level. Messages below this level are suppressed.
|
|
23
|
+
* Default is "info" in production, "debug" in development.
|
|
24
|
+
*/
|
|
25
|
+
declare function setLogLevel(level: LogLevel): void;
|
|
26
|
+
/**
|
|
27
|
+
* Get the current log level.
|
|
28
|
+
*/
|
|
29
|
+
declare function getLogLevel(): LogLevel;
|
|
30
|
+
declare function setLogAdapter(a: LogAdapter): void;
|
|
31
|
+
/**
|
|
32
|
+
* Reset adapter callbacks to defaults (no-op adapter).
|
|
33
|
+
* For testing/integration teardown only.
|
|
34
|
+
*/
|
|
35
|
+
declare function clearLogAdapter(): void;
|
|
36
|
+
/** Reset log level to runtime default (info in prod, debug otherwise). */
|
|
37
|
+
declare function resetLogLevel(): void;
|
|
38
|
+
declare function logDebug(context: string, data?: unknown): void;
|
|
39
|
+
declare function logError(context: string, error?: unknown): void;
|
|
40
|
+
declare function logWarn(context: string, message?: string): void;
|
|
41
|
+
declare function logInfo(context: string, data?: unknown): void;
|
|
42
|
+
declare function logSecurityEvent(event: SecurityEventType, data?: SecurityLogData): void;
|
|
43
|
+
|
|
44
|
+
export { type LogAdapter, type LogLevel, clearLogAdapter, getLogLevel, logDebug, logError, logInfo, logSecurityEvent, logWarn, resetLogLevel, setLogAdapter, setLogLevel };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearLogAdapter,
|
|
3
|
+
getLogLevel,
|
|
4
|
+
logDebug,
|
|
5
|
+
logError,
|
|
6
|
+
logInfo,
|
|
7
|
+
logSecurityEvent,
|
|
8
|
+
logWarn,
|
|
9
|
+
resetLogLevel,
|
|
10
|
+
setLogAdapter,
|
|
11
|
+
setLogLevel
|
|
12
|
+
} from "../chunk-KX32MU3I.js";
|
|
13
|
+
import "../chunk-EFUBAQCV.js";
|
|
14
|
+
import "../chunk-PT4DIYUK.js";
|
|
15
|
+
export {
|
|
16
|
+
clearLogAdapter,
|
|
17
|
+
getLogLevel,
|
|
18
|
+
logDebug,
|
|
19
|
+
logError,
|
|
20
|
+
logInfo,
|
|
21
|
+
logSecurityEvent,
|
|
22
|
+
logWarn,
|
|
23
|
+
resetLogLevel,
|
|
24
|
+
setLogAdapter,
|
|
25
|
+
setLogLevel
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { M as MiddlewareOptions } from '../middleware-registry-DT002qRd.js';
|
|
2
|
+
export { c as clearAllMiddleware, g as getMiddlewareRunner, a as getRegisteredMiddlewareSlots, r as registerMiddleware } from '../middleware-registry-DT002qRd.js';
|
|
3
|
+
import { a as MiddlewareFn } from '../middleware-types-DVG9C1qJ.js';
|
|
4
|
+
export { A as ApiRequestContext, F as FormDeleteContext, c as FormLoadContext, d as FormSaveContext, L as ListLoadContext, b as MiddlewareEntry, M as MiddlewareSlot, e as MiddlewareSlotMap } from '../middleware-types-DVG9C1qJ.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Audit middleware — standardized audit event creation for form mutations.
|
|
8
|
+
*
|
|
9
|
+
* Provides a typed `AuditEvent` and factory functions that hook into
|
|
10
|
+
* `form:afterSave` and `form:afterDelete` to produce audit events for every
|
|
11
|
+
* successful create, update, or delete operation.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { createAuditMiddleware } from "@spring-systems/core/middleware";
|
|
16
|
+
*
|
|
17
|
+
* // Send audit events to your backend:
|
|
18
|
+
* const unregister = createAuditMiddleware(async (event) => {
|
|
19
|
+
* await fetch("/api/audit", {
|
|
20
|
+
* method: "POST",
|
|
21
|
+
* headers: { "Content-Type": "application/json" },
|
|
22
|
+
* body: JSON.stringify(event),
|
|
23
|
+
* });
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Or log to console during development:
|
|
27
|
+
* createAuditMiddleware((event) => {
|
|
28
|
+
* console.log(`[Audit] ${event.action} ${event.entity}#${event.entityId}`, event);
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @module audit-middleware
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
interface AuditEvent {
|
|
36
|
+
/** Mutation type */
|
|
37
|
+
action: "create" | "update" | "delete";
|
|
38
|
+
/** Entity type name (e.g. "partner", "user") */
|
|
39
|
+
entity: string;
|
|
40
|
+
/** Entity record identifier */
|
|
41
|
+
entityId: string;
|
|
42
|
+
/** ISO 8601 timestamp of the event */
|
|
43
|
+
timestamp: string;
|
|
44
|
+
/** API endpoint URL used for the operation */
|
|
45
|
+
url: string;
|
|
46
|
+
/** Field values included in the save payload (empty object for deletes) */
|
|
47
|
+
fields: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
type AuditEventHandler = (event: AuditEvent) => void | Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Create and register audit middleware that emits `AuditEvent` for every
|
|
52
|
+
* successful form save (create or update) and delete operation.
|
|
53
|
+
*
|
|
54
|
+
* The middleware hooks into both `form:afterSave` and `form:afterDelete` slots.
|
|
55
|
+
* Aborted operations are silently skipped.
|
|
56
|
+
*
|
|
57
|
+
* @param handler - Callback that receives the audit event. Can be sync or async.
|
|
58
|
+
* Async errors are caught and logged to prevent audit failures
|
|
59
|
+
* from breaking the operation flow.
|
|
60
|
+
* @param options - Optional middleware options (e.g. `{ priority: 10 }`)
|
|
61
|
+
* @returns An unregister function that removes both audit middleware registrations.
|
|
62
|
+
*/
|
|
63
|
+
declare function createAuditMiddleware(handler: AuditEventHandler, options?: MiddlewareOptions): () => void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Koa-style middleware composition.
|
|
67
|
+
* Chains middleware functions with a `next()` pattern.
|
|
68
|
+
* @module middleware-runner
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
interface ComposeOptions {
|
|
72
|
+
/**
|
|
73
|
+
* Optional timeout in milliseconds for the entire middleware chain.
|
|
74
|
+
* If the chain doesn't complete within this time, a SpringMiddlewareError is thrown.
|
|
75
|
+
* When omitted, no timeout is applied (backward-compatible default).
|
|
76
|
+
*/
|
|
77
|
+
timeoutMs?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Compose an array of middleware functions into a single function.
|
|
81
|
+
* Each middleware receives a context and a `next` callback.
|
|
82
|
+
* Calling `next()` invokes the next middleware in the chain.
|
|
83
|
+
* Calling `next()` more than once throws an error.
|
|
84
|
+
*
|
|
85
|
+
* @param middlewares - Array of middleware functions to compose
|
|
86
|
+
* @param options - Optional configuration (e.g. timeout)
|
|
87
|
+
* @returns A function that runs the full middleware chain on a given context.
|
|
88
|
+
*/
|
|
89
|
+
declare function composeMiddleware<TContext>(middlewares: ReadonlyArray<MiddlewareFn<TContext>>, options?: ComposeOptions): (ctx: TContext) => Promise<void>;
|
|
90
|
+
|
|
91
|
+
export { type AuditEvent, type AuditEventHandler, type ComposeOptions, MiddlewareFn, MiddlewareOptions, composeMiddleware, createAuditMiddleware };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAuditMiddleware
|
|
3
|
+
} from "../chunk-SQB4F3EF.js";
|
|
4
|
+
import {
|
|
5
|
+
clearAllMiddleware,
|
|
6
|
+
composeMiddleware,
|
|
7
|
+
getMiddlewareRunner,
|
|
8
|
+
getRegisteredMiddlewareSlots,
|
|
9
|
+
registerMiddleware
|
|
10
|
+
} from "../chunk-MEWPYTWC.js";
|
|
11
|
+
import "../chunk-RUCXSQEY.js";
|
|
12
|
+
import "../chunk-KX32MU3I.js";
|
|
13
|
+
import "../chunk-EFUBAQCV.js";
|
|
14
|
+
import "../chunk-PT4DIYUK.js";
|
|
15
|
+
export {
|
|
16
|
+
clearAllMiddleware,
|
|
17
|
+
composeMiddleware,
|
|
18
|
+
createAuditMiddleware,
|
|
19
|
+
getMiddlewareRunner,
|
|
20
|
+
getRegisteredMiddlewareSlots,
|
|
21
|
+
registerMiddleware
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { M as MiddlewareSlot, a as MiddlewareFn } from './middleware-types-DVG9C1qJ.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Middleware registry — manages middleware functions registered per slot.
|
|
5
|
+
*
|
|
6
|
+
* Type-safe: the context type is inferred from the slot name via MiddlewareSlotMap.
|
|
7
|
+
* Custom slots added via declaration merging also get full type inference.
|
|
8
|
+
*
|
|
9
|
+
* @module middleware-registry
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
interface MiddlewareOptions {
|
|
13
|
+
/** Higher priority middleware runs first. Default: 0 */
|
|
14
|
+
priority?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Register a middleware function for a given slot.
|
|
18
|
+
* The context type is automatically inferred from the slot name via MiddlewareSlotMap.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Context type is inferred as FormSaveContext
|
|
23
|
+
* const unregister = registerMiddleware("form:beforeSave", async (ctx, next) => {
|
|
24
|
+
* console.log("Saving entity:", ctx.entity);
|
|
25
|
+
* await next();
|
|
26
|
+
* });
|
|
27
|
+
* unregister(); // Cleanup when no longer needed
|
|
28
|
+
*
|
|
29
|
+
* // With priority (higher = runs first):
|
|
30
|
+
* registerMiddleware("form:beforeSave", auditMiddleware, { priority: 10 });
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param slot - Middleware slot name (e.g. "form:beforeSave", "api:beforeRequest")
|
|
34
|
+
* @param middleware - Koa-style middleware function receiving `(ctx, next)`
|
|
35
|
+
* @param options - Optional settings; `priority` controls execution order (higher runs first, default 0)
|
|
36
|
+
* @returns An unregister function that removes this middleware from the slot.
|
|
37
|
+
*/
|
|
38
|
+
declare function registerMiddleware<TContext = unknown>(slot: MiddlewareSlot, middleware: MiddlewareFn<TContext>, options?: MiddlewareOptions): () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Get a composed runner for a given slot.
|
|
41
|
+
* Returns a function that executes all registered middleware for that slot
|
|
42
|
+
* in priority order (higher priority first) using the Koa-style `next()` pattern.
|
|
43
|
+
*
|
|
44
|
+
* If no middleware is registered for the slot, the returned function is a no-op.
|
|
45
|
+
*
|
|
46
|
+
* @param slot - Middleware slot name to compose a runner for
|
|
47
|
+
* @returns An async function that runs all middleware for the slot on a given context.
|
|
48
|
+
*/
|
|
49
|
+
declare function getMiddlewareRunner<TContext = unknown>(slot: MiddlewareSlot): (ctx: TContext) => Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Get all slot names that have at least one middleware registered.
|
|
52
|
+
* Useful for debugging and introspection.
|
|
53
|
+
*/
|
|
54
|
+
declare function getRegisteredMiddlewareSlots(): MiddlewareSlot[];
|
|
55
|
+
/**
|
|
56
|
+
* Remove all registered middleware. Intended for testing.
|
|
57
|
+
*/
|
|
58
|
+
declare function clearAllMiddleware(): void;
|
|
59
|
+
|
|
60
|
+
export { type MiddlewareOptions as M, getRegisteredMiddlewareSlots as a, clearAllMiddleware as c, getMiddlewareRunner as g, registerMiddleware as r };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware type definitions for form, list, and API operations.
|
|
3
|
+
*
|
|
4
|
+
* Middleware slots are extensible via declaration merging on MiddlewareSlotMap.
|
|
5
|
+
* Consumer projects and plugins can add custom slots:
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* // In your plugin or consumer project:
|
|
10
|
+
* declare module "@spring-systems/core/middleware" {
|
|
11
|
+
* interface MiddlewareSlotMap {
|
|
12
|
+
* "custom:beforeExport": { format: string; data: unknown[] };
|
|
13
|
+
* "custom:afterImport": { count: number; errors: string[] };
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @module middleware-types
|
|
19
|
+
*/
|
|
20
|
+
type MiddlewareFn<TContext> = (ctx: TContext, next: () => Promise<void>) => Promise<void>;
|
|
21
|
+
/** Internal entry stored in the registry — pairs a middleware function with its priority. */
|
|
22
|
+
interface MiddlewareEntry<TContext = unknown> {
|
|
23
|
+
fn: MiddlewareFn<TContext>;
|
|
24
|
+
priority: number;
|
|
25
|
+
}
|
|
26
|
+
interface FormLoadContext {
|
|
27
|
+
entity: string;
|
|
28
|
+
id: string;
|
|
29
|
+
url: string;
|
|
30
|
+
data?: unknown;
|
|
31
|
+
aborted: boolean;
|
|
32
|
+
result?: unknown;
|
|
33
|
+
}
|
|
34
|
+
interface FormSaveContext {
|
|
35
|
+
entity: string;
|
|
36
|
+
id: string;
|
|
37
|
+
url: string;
|
|
38
|
+
fields: Record<string, unknown>;
|
|
39
|
+
isNew: boolean;
|
|
40
|
+
aborted: boolean;
|
|
41
|
+
result?: unknown;
|
|
42
|
+
}
|
|
43
|
+
interface FormDeleteContext {
|
|
44
|
+
entity: string;
|
|
45
|
+
id: string;
|
|
46
|
+
url: string;
|
|
47
|
+
aborted: boolean;
|
|
48
|
+
result?: unknown;
|
|
49
|
+
}
|
|
50
|
+
interface ListLoadContext {
|
|
51
|
+
apiUrl: string;
|
|
52
|
+
requestData: unknown;
|
|
53
|
+
aborted: boolean;
|
|
54
|
+
result?: unknown;
|
|
55
|
+
}
|
|
56
|
+
interface ApiRequestContext {
|
|
57
|
+
url: string;
|
|
58
|
+
method: string;
|
|
59
|
+
data?: unknown;
|
|
60
|
+
headers?: Record<string, string>;
|
|
61
|
+
aborted: boolean;
|
|
62
|
+
response?: unknown;
|
|
63
|
+
error?: unknown;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extensible middleware slot map. Keys are slot names, values are context types.
|
|
67
|
+
* Extend via declaration merging to add custom slots.
|
|
68
|
+
*/
|
|
69
|
+
interface MiddlewareSlotMap {
|
|
70
|
+
"form:beforeLoad": FormLoadContext;
|
|
71
|
+
"form:afterLoad": FormLoadContext;
|
|
72
|
+
"form:beforeSave": FormSaveContext;
|
|
73
|
+
"form:afterSave": FormSaveContext;
|
|
74
|
+
"form:beforeDelete": FormDeleteContext;
|
|
75
|
+
"form:afterDelete": FormDeleteContext;
|
|
76
|
+
"list:beforeLoad": ListLoadContext;
|
|
77
|
+
"list:afterLoad": ListLoadContext;
|
|
78
|
+
"api:beforeRequest": ApiRequestContext;
|
|
79
|
+
"api:afterResponse": ApiRequestContext;
|
|
80
|
+
"api:onError": ApiRequestContext;
|
|
81
|
+
}
|
|
82
|
+
/** Union of all registered middleware slot names (auto-expands with declaration merging) */
|
|
83
|
+
type MiddlewareSlot = keyof MiddlewareSlotMap;
|
|
84
|
+
|
|
85
|
+
export type { ApiRequestContext as A, FormDeleteContext as F, ListLoadContext as L, MiddlewareSlot as M, MiddlewareFn as a, MiddlewareEntry as b, FormLoadContext as c, FormSaveContext as d, MiddlewareSlotMap as e };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { d as SpringInstance } from '../spring-instance-EbUh4mQb.js';
|
|
2
|
+
import { a as FormDataValue, b as FormStoreState, c as ColumnType } from '../form-types-D3MdGpjA.js';
|
|
3
|
+
import '../framework-config-types-DeUbx4bu.js';
|
|
4
|
+
import '../middleware-types-DVG9C1qJ.js';
|
|
5
|
+
import '../security-sanitize-Bb0PExM6.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Plugin system for the SPRING framework.
|
|
9
|
+
*
|
|
10
|
+
* A plugin can be either:
|
|
11
|
+
* - A simple setup function (backward compatible): `(instance) => cleanup?`
|
|
12
|
+
* - A plugin descriptor with metadata: `{ name, version, setup, ... }`
|
|
13
|
+
*
|
|
14
|
+
* Plugin descriptors enable:
|
|
15
|
+
* - Dependency declaration and topological ordering
|
|
16
|
+
* - Capability requirements checking
|
|
17
|
+
* - Version compatibility validation
|
|
18
|
+
* - Plugin discovery and introspection
|
|
19
|
+
*
|
|
20
|
+
* @module plugin
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** Column renderer info passed to custom renderers. */
|
|
24
|
+
interface PluginColumnRendererInfo {
|
|
25
|
+
field: string;
|
|
26
|
+
type: ColumnType;
|
|
27
|
+
title: string;
|
|
28
|
+
suffix?: string;
|
|
29
|
+
decimals?: number;
|
|
30
|
+
name?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Column renderer function signature.
|
|
34
|
+
* Returns a React node (any valid JSX return value).
|
|
35
|
+
*/
|
|
36
|
+
type PluginColumnRenderer = (value: FormDataValue, row: FormStoreState, column: PluginColumnRendererInfo) => unknown;
|
|
37
|
+
/** Simple plugin function (backward compatible) */
|
|
38
|
+
type SpringPluginFn = (instance: SpringInstance) => void | (() => void);
|
|
39
|
+
/**
|
|
40
|
+
* Plugin descriptor with metadata for enterprise plugin management.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const auditPlugin: SpringPluginDescriptor = {
|
|
45
|
+
* name: "@spring-systems/audit",
|
|
46
|
+
* version: "1.0.0",
|
|
47
|
+
* requires: ["@spring-systems/core-validators"],
|
|
48
|
+
* capabilities: ["advancedFiltering"],
|
|
49
|
+
* setup(instance) {
|
|
50
|
+
* registerMiddleware("form:beforeSave", auditMiddleware);
|
|
51
|
+
* return () => { cleanup(); };
|
|
52
|
+
* },
|
|
53
|
+
* };
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
interface SpringPluginDescriptor {
|
|
57
|
+
/** Unique plugin name. Use npm-style scoped names (e.g. "@myorg/plugin-name"). */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Semver version string. */
|
|
60
|
+
version?: string;
|
|
61
|
+
/** Names of plugins that must be loaded before this one. */
|
|
62
|
+
requires?: string[];
|
|
63
|
+
/** Capability keys that must be enabled for this plugin to activate. */
|
|
64
|
+
capabilities?: string[];
|
|
65
|
+
/** Plugin setup function. Returns optional cleanup. */
|
|
66
|
+
setup: SpringPluginFn;
|
|
67
|
+
/**
|
|
68
|
+
* Explicit cleanup function. Called by `disposePlugins()` alongside any
|
|
69
|
+
* cleanup returned from `setup()`. Also available for direct invocation
|
|
70
|
+
* by consumers who hold a reference to the descriptor.
|
|
71
|
+
*/
|
|
72
|
+
cleanup?: () => void;
|
|
73
|
+
}
|
|
74
|
+
/** A SPRING plugin — either a simple function or a descriptor with metadata. */
|
|
75
|
+
type SpringPlugin = SpringPluginFn | SpringPluginDescriptor;
|
|
76
|
+
interface LoadedPluginInfo {
|
|
77
|
+
name: string;
|
|
78
|
+
version?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Apply an array of plugins to a SpringInstance.
|
|
82
|
+
* Plugins with dependencies are topologically sorted.
|
|
83
|
+
* Each may return a cleanup function stored on the instance.
|
|
84
|
+
*
|
|
85
|
+
* Setup errors are caught and logged — a failing plugin does not block others.
|
|
86
|
+
*
|
|
87
|
+
* @param instance - The SpringInstance to apply plugins to
|
|
88
|
+
* @param plugins - Array of plugins (simple functions or descriptors with metadata)
|
|
89
|
+
*/
|
|
90
|
+
declare function applyPlugins(instance: SpringInstance, plugins: SpringPlugin[]): void;
|
|
91
|
+
/**
|
|
92
|
+
* Run all cleanup functions stored by `applyPlugins()` and remove them
|
|
93
|
+
* from the instance. Errors during cleanup are caught and logged.
|
|
94
|
+
*
|
|
95
|
+
* @param instance - The SpringInstance whose plugins should be disposed
|
|
96
|
+
*/
|
|
97
|
+
declare function disposePlugins(instance: SpringInstance): void;
|
|
98
|
+
/**
|
|
99
|
+
* Get the list of loaded plugins for the given instance.
|
|
100
|
+
* Useful for debugging and introspection.
|
|
101
|
+
*/
|
|
102
|
+
declare function getLoadedPlugins(instance: SpringInstance): ReadonlyArray<LoadedPluginInfo>;
|
|
103
|
+
|
|
104
|
+
export { type PluginColumnRenderer, type PluginColumnRendererInfo, type SpringPlugin, type SpringPluginDescriptor, type SpringPluginFn, applyPlugins, disposePlugins, getLoadedPlugins };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyPlugins,
|
|
3
|
+
disposePlugins,
|
|
4
|
+
getLoadedPlugins
|
|
5
|
+
} from "../chunk-GXU75LQX.js";
|
|
6
|
+
import "../chunk-S7MKRNMI.js";
|
|
7
|
+
import "../chunk-RUCXSQEY.js";
|
|
8
|
+
import "../chunk-KX32MU3I.js";
|
|
9
|
+
import "../chunk-EFUBAQCV.js";
|
|
10
|
+
import "../chunk-PT4DIYUK.js";
|
|
11
|
+
export {
|
|
12
|
+
applyPlugins,
|
|
13
|
+
disposePlugins,
|
|
14
|
+
getLoadedPlugins
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|