@jskit-ai/kernel 0.1.245 → 0.1.247
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/client/appConfig.js +2 -1
- package/client/asyncModuleRecovery.js +2 -4
- package/client/index.d.ts +13 -75
- package/client/index.js +1 -1
- package/client/logging.js +8 -2
- package/client/moduleBootstrap.js +41 -33
- package/client/moduleBootstrap.test.js +35 -0
- package/client/shellBootstrap.js +1 -8
- package/client/shellBootstrap.test.js +32 -5
- package/client/shellRouting.js +16 -61
- package/client/shellRouting.test.js +30 -1
- package/client/vite/clientBootstrapPlugin.js +0 -6
- package/client/vite/clientBootstrapPlugin.test.js +2 -3
- package/internal/node/installedPackages.js +19 -62
- package/internal/node/installedPackages.test.js +33 -0
- package/package.json +2 -4
- package/server/actions/actionCatalogue.js +13 -34
- package/{shared → server}/actions/actionContributorHelpers.js +0 -5
- package/{shared → server}/actions/actionDefinitions.js +24 -131
- package/{shared → server}/actions/actionDefinitions.test.js +75 -21
- package/server/actions/actionEvents.js +97 -2
- package/server/actions/actionEvents.test.js +79 -0
- package/{shared → server}/actions/executionContext.js +3 -13
- package/server/actions/idempotency.js +24 -0
- package/server/actions/pipeline.js +87 -0
- package/{shared → server}/actions/policies.js +20 -33
- package/{shared → server}/actions/policies.test.js +6 -6
- package/{shared → server}/actions/registry.js +3 -22
- package/{shared → server}/actions/registry.test.js +70 -32
- package/server/actions/requestMeta.js +17 -0
- package/server/http/capabilityHttpRuntime.js +1 -1
- package/server/http/capabilityHttpRuntime.test.js +56 -0
- package/server/http/errorHandling.js +291 -0
- package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
- package/server/http/lib/routeRegistration.js +36 -150
- package/server/http/lib/routeTransport.js +2 -0
- package/server/http/lib/routeValidator.js +5 -47
- package/server/http/lib/routeValidator.test.js +15 -17
- package/server/http/lib/router.js +10 -94
- package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
- package/server/platform/providerRuntime/helpers.js +1 -34
- package/server/runtime/integers.js +1 -5
- package/server/runtime/serviceAuthorization.js +4 -9
- package/server/support/appConfig.js +2 -1
- package/server/support/appConfigFiles.js +1 -38
- package/server/support/appConfigFiles.test.js +3 -39
- package/server/support/index.js +1 -20
- package/shared/capabilities/defineProvider.js +1 -1
- package/shared/capabilities/index.js +1 -1
- package/shared/index.js +1 -1
- package/shared/support/index.js +1 -4
- package/shared/support/mobileConfig.js +99 -0
- package/shared/support/mobileConfig.test.js +113 -0
- package/shared/support/normalize.js +0 -108
- package/shared/support/normalize.test.js +0 -134
- package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
- package/shared/support/returnToPath.js +1 -20
- package/shared/support/returnToPath.test.js +1 -36
- package/shared/support/shellLayoutTargets.js +2 -140
- package/shared/support/shellLayoutTargets.test.js +1 -110
- package/shared/support/sorting.js +1 -9
- package/shared/surface/apiPaths.js +1 -82
- package/shared/surface/paths.js +38 -171
- package/shared/surface/registry.js +2 -1
- package/shared/surface/runtime.js +18 -109
- package/shared/surface/runtime.test.js +57 -0
- package/shared/validators/index.js +1 -4
- package/shared/validators/jsonRestSchemaSupport.js +0 -9
- package/shared/validators/recordIdParamsValidator.js +0 -6
- package/shared/validators/schemaDefinitions.js +4 -30
- package/shared/validators/schemaPayloadValidation.js +2 -6
- package/test/barrelExposure.test.js +3 -7
- package/test/exportsContract.test.js +1 -3
- package/client/mobileLaunchRouting.js +0 -231
- package/client/mobileLaunchRouting.test.js +0 -230
- package/server/http/lib/controller.js +0 -183
- package/server/http/lib/controller.test.js +0 -143
- package/server/http/lib/index.js +0 -5
- package/server/runtime/canonicalJson.js +0 -74
- package/server/runtime/entityChangeEvents.js +0 -307
- package/server/runtime/entityChangeEvents.test.js +0 -274
- package/server/runtime/fastifyBootstrap.js +0 -553
- package/server/runtime/moduleConfig.js +0 -223
- package/server/runtime/moduleConfig.test.js +0 -165
- package/server/runtime/pagination.js +0 -13
- package/server/runtime/realtimeNormalization.js +0 -21
- package/server/runtime/routeUtils.js +0 -20
- package/server/runtime/securityAudit.js +0 -269
- package/server/runtime/securityAudit.test.js +0 -41
- package/server/support/pageTargets.js +0 -772
- package/server/support/pageTargets.test.js +0 -659
- package/server/support/shellOutlets.js +0 -576
- package/server/support/shellOutlets.test.js +0 -336
- package/server/surface/index.js +0 -18
- package/shared/actions/audit.js +0 -7
- package/shared/actions/idempotency.js +0 -62
- package/shared/actions/observability.js +0 -10
- package/shared/actions/pipeline.js +0 -309
- package/shared/actions/requestMeta.js +0 -36
- package/shared/actions/textNormalization.js +0 -3
- package/shared/actions/withActionDefaults.js +0 -34
- /package/{shared → server}/actions/executionContext.test.js +0 -0
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ensureActionChannelAllowed,
|
|
3
|
-
ensureActionSurfaceAllowed,
|
|
4
|
-
ensureActionPermissionAllowed,
|
|
5
|
-
normalizeActionInput,
|
|
6
|
-
normalizeActionOutput
|
|
7
|
-
} from "./policies.js";
|
|
8
|
-
import {
|
|
9
|
-
createNoopIdempotencyAdapter,
|
|
10
|
-
resolveActionIdempotencyKey,
|
|
11
|
-
ensureIdempotencyKeyIfRequired
|
|
12
|
-
} from "./idempotency.js";
|
|
13
|
-
import { createNoopAuditAdapter } from "./audit.js";
|
|
14
|
-
import { createNoopObservabilityAdapter } from "./observability.js";
|
|
15
|
-
import { normalizeExecutionContext } from "./executionContext.js";
|
|
16
|
-
|
|
17
|
-
async function publishActionEvents(events, builders, execution) {
|
|
18
|
-
if (!Array.isArray(builders) || builders.length === 0) return;
|
|
19
|
-
if (!events || typeof events.publish !== "function") {
|
|
20
|
-
throw new TypeError("Action event publishing requires runtime.events.publish().");
|
|
21
|
-
}
|
|
22
|
-
for (const builder of builders) {
|
|
23
|
-
const built = await builder(execution);
|
|
24
|
-
const values = Array.isArray(built) ? built : [built];
|
|
25
|
-
for (const event of values) {
|
|
26
|
-
if (event != null) await events.publish(event);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function normalizeOutcomeErrorCode(error) {
|
|
32
|
-
return String(error?.code || "ACTION_EXECUTION_FAILED").trim();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function buildActionLogPayload({ definition, context, outcome, durationMs, errorCode, idempotencyReplay }) {
|
|
36
|
-
return {
|
|
37
|
-
action: definition?.id,
|
|
38
|
-
version: definition?.version,
|
|
39
|
-
channel: context?.channel,
|
|
40
|
-
surface: context?.surface,
|
|
41
|
-
requestId: context?.requestMeta?.requestId || null,
|
|
42
|
-
durationMs,
|
|
43
|
-
outcome,
|
|
44
|
-
errorCode: errorCode || null,
|
|
45
|
-
idempotencyReplay: Boolean(idempotencyReplay)
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function emitAuditEvent(adapter, payload) {
|
|
50
|
-
if (!adapter || typeof adapter.emitExecution !== "function") {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
await adapter.emitExecution(payload);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function executeIdempotencyClaim(adapter, payload) {
|
|
58
|
-
if (!adapter || typeof adapter.claimOrReplay !== "function") {
|
|
59
|
-
return {
|
|
60
|
-
type: "proceed",
|
|
61
|
-
idempotencyReplay: false,
|
|
62
|
-
claim: null,
|
|
63
|
-
replayResult: null
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const result = await adapter.claimOrReplay(payload);
|
|
68
|
-
if (!result || typeof result !== "object") {
|
|
69
|
-
return {
|
|
70
|
-
type: "proceed",
|
|
71
|
-
idempotencyReplay: false,
|
|
72
|
-
claim: null,
|
|
73
|
-
replayResult: null
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
type: String(result.type || "proceed"),
|
|
79
|
-
idempotencyReplay: result.idempotencyReplay === true,
|
|
80
|
-
claim: result.claim || null,
|
|
81
|
-
replayResult: Object.hasOwn(result, "replayResult") ? result.replayResult : null
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async function executeActionPipeline({
|
|
86
|
-
definition,
|
|
87
|
-
input,
|
|
88
|
-
context,
|
|
89
|
-
deps = {},
|
|
90
|
-
idempotencyAdapter,
|
|
91
|
-
auditAdapter,
|
|
92
|
-
observabilityAdapter,
|
|
93
|
-
events,
|
|
94
|
-
logger = console
|
|
95
|
-
} = {}) {
|
|
96
|
-
const normalizedContext = normalizeExecutionContext(context);
|
|
97
|
-
const normalizedIdempotencyAdapter = idempotencyAdapter || createNoopIdempotencyAdapter();
|
|
98
|
-
const normalizedAuditAdapter = auditAdapter || createNoopAuditAdapter();
|
|
99
|
-
const normalizedObservabilityAdapter = observabilityAdapter || createNoopObservabilityAdapter();
|
|
100
|
-
const startedAt = Date.now();
|
|
101
|
-
|
|
102
|
-
if (typeof normalizedObservabilityAdapter.recordExecutionStart === "function") {
|
|
103
|
-
normalizedObservabilityAdapter.recordExecutionStart({
|
|
104
|
-
definition,
|
|
105
|
-
context: normalizedContext
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
let idempotencyKey = "";
|
|
110
|
-
let idempotencyClaim = null;
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
ensureActionChannelAllowed(definition, normalizedContext);
|
|
114
|
-
ensureActionSurfaceAllowed(definition, normalizedContext);
|
|
115
|
-
ensureActionPermissionAllowed(definition, normalizedContext);
|
|
116
|
-
|
|
117
|
-
const normalizedInput = await normalizeActionInput(definition, input, normalizedContext);
|
|
118
|
-
|
|
119
|
-
idempotencyKey = resolveActionIdempotencyKey(definition, normalizedContext);
|
|
120
|
-
ensureIdempotencyKeyIfRequired(definition, normalizedContext, idempotencyKey);
|
|
121
|
-
|
|
122
|
-
const idempotencyPolicy = String(definition?.idempotency || "none").trim().toLowerCase();
|
|
123
|
-
if (idempotencyPolicy !== "none") {
|
|
124
|
-
const claimResult = await executeIdempotencyClaim(normalizedIdempotencyAdapter, {
|
|
125
|
-
definition,
|
|
126
|
-
context: normalizedContext,
|
|
127
|
-
input: normalizedInput,
|
|
128
|
-
idempotencyKey
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
idempotencyClaim = claimResult.claim;
|
|
132
|
-
if (claimResult.type === "replay") {
|
|
133
|
-
if (typeof normalizedObservabilityAdapter.recordIdempotentReplay === "function") {
|
|
134
|
-
normalizedObservabilityAdapter.recordIdempotentReplay({
|
|
135
|
-
definition,
|
|
136
|
-
context: normalizedContext
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const replayDurationMs = Date.now() - startedAt;
|
|
141
|
-
if (typeof normalizedObservabilityAdapter.recordExecutionFinish === "function") {
|
|
142
|
-
normalizedObservabilityAdapter.recordExecutionFinish({
|
|
143
|
-
definition,
|
|
144
|
-
context: normalizedContext,
|
|
145
|
-
outcome: "replay",
|
|
146
|
-
durationMs: replayDurationMs,
|
|
147
|
-
idempotencyReplay: true
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
await emitAuditEvent(normalizedAuditAdapter, {
|
|
152
|
-
definition,
|
|
153
|
-
context: normalizedContext,
|
|
154
|
-
outcome: "success",
|
|
155
|
-
result: claimResult.replayResult,
|
|
156
|
-
error: null,
|
|
157
|
-
durationMs: replayDurationMs,
|
|
158
|
-
idempotencyReplay: true
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
if (logger && typeof logger.debug === "function") {
|
|
162
|
-
logger.debug(
|
|
163
|
-
buildActionLogPayload({
|
|
164
|
-
definition,
|
|
165
|
-
context: normalizedContext,
|
|
166
|
-
outcome: "replay",
|
|
167
|
-
durationMs: replayDurationMs,
|
|
168
|
-
errorCode: null,
|
|
169
|
-
idempotencyReplay: true
|
|
170
|
-
}),
|
|
171
|
-
"action.execution"
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
result: claimResult.replayResult,
|
|
177
|
-
idempotencyReplay: true
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const executionResult = await definition.execute(normalizedInput, normalizedContext, deps);
|
|
183
|
-
const normalizedResult = await normalizeActionOutput(definition, executionResult, normalizedContext);
|
|
184
|
-
|
|
185
|
-
await publishActionEvents(events, definition.events, Object.freeze({
|
|
186
|
-
definition,
|
|
187
|
-
input: normalizedInput,
|
|
188
|
-
result: normalizedResult,
|
|
189
|
-
context: normalizedContext
|
|
190
|
-
}));
|
|
191
|
-
|
|
192
|
-
if (idempotencyClaim && typeof normalizedIdempotencyAdapter.markSucceeded === "function") {
|
|
193
|
-
await normalizedIdempotencyAdapter.markSucceeded({
|
|
194
|
-
definition,
|
|
195
|
-
context: normalizedContext,
|
|
196
|
-
input: normalizedInput,
|
|
197
|
-
result: normalizedResult,
|
|
198
|
-
claim: idempotencyClaim,
|
|
199
|
-
idempotencyKey
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const durationMs = Date.now() - startedAt;
|
|
204
|
-
if (typeof normalizedObservabilityAdapter.recordExecutionFinish === "function") {
|
|
205
|
-
normalizedObservabilityAdapter.recordExecutionFinish({
|
|
206
|
-
definition,
|
|
207
|
-
context: normalizedContext,
|
|
208
|
-
outcome: "success",
|
|
209
|
-
durationMs,
|
|
210
|
-
idempotencyReplay: false
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
await emitAuditEvent(normalizedAuditAdapter, {
|
|
215
|
-
definition,
|
|
216
|
-
context: normalizedContext,
|
|
217
|
-
outcome: "success",
|
|
218
|
-
result: normalizedResult,
|
|
219
|
-
error: null,
|
|
220
|
-
durationMs,
|
|
221
|
-
idempotencyReplay: false
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
if (logger && typeof logger.debug === "function") {
|
|
225
|
-
logger.debug(
|
|
226
|
-
buildActionLogPayload({
|
|
227
|
-
definition,
|
|
228
|
-
context: normalizedContext,
|
|
229
|
-
outcome: "success",
|
|
230
|
-
durationMs,
|
|
231
|
-
errorCode: null,
|
|
232
|
-
idempotencyReplay: false
|
|
233
|
-
}),
|
|
234
|
-
"action.execution"
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return {
|
|
239
|
-
result: normalizedResult,
|
|
240
|
-
idempotencyReplay: false
|
|
241
|
-
};
|
|
242
|
-
} catch (error) {
|
|
243
|
-
const executionError = error;
|
|
244
|
-
|
|
245
|
-
if (executionError?.code === "ACTION_VALIDATION_FAILED") {
|
|
246
|
-
if (typeof normalizedObservabilityAdapter.recordValidationFailure === "function") {
|
|
247
|
-
normalizedObservabilityAdapter.recordValidationFailure({
|
|
248
|
-
definition,
|
|
249
|
-
context: normalizedContext,
|
|
250
|
-
error: executionError
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (idempotencyClaim && typeof normalizedIdempotencyAdapter.markFailed === "function") {
|
|
256
|
-
await normalizedIdempotencyAdapter.markFailed({
|
|
257
|
-
definition,
|
|
258
|
-
context: normalizedContext,
|
|
259
|
-
input,
|
|
260
|
-
error: executionError,
|
|
261
|
-
claim: idempotencyClaim,
|
|
262
|
-
idempotencyKey
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const durationMs = Date.now() - startedAt;
|
|
267
|
-
const errorCode = normalizeOutcomeErrorCode(executionError);
|
|
268
|
-
|
|
269
|
-
if (typeof normalizedObservabilityAdapter.recordExecutionFinish === "function") {
|
|
270
|
-
normalizedObservabilityAdapter.recordExecutionFinish({
|
|
271
|
-
definition,
|
|
272
|
-
context: normalizedContext,
|
|
273
|
-
outcome: "failure",
|
|
274
|
-
durationMs,
|
|
275
|
-
error: executionError,
|
|
276
|
-
errorCode,
|
|
277
|
-
idempotencyReplay: false
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
await emitAuditEvent(normalizedAuditAdapter, {
|
|
282
|
-
definition,
|
|
283
|
-
context: normalizedContext,
|
|
284
|
-
outcome: "failure",
|
|
285
|
-
result: null,
|
|
286
|
-
error: executionError,
|
|
287
|
-
durationMs,
|
|
288
|
-
idempotencyReplay: false
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
if (logger && typeof logger.debug === "function") {
|
|
292
|
-
logger.debug(
|
|
293
|
-
buildActionLogPayload({
|
|
294
|
-
definition,
|
|
295
|
-
context: normalizedContext,
|
|
296
|
-
outcome: "failure",
|
|
297
|
-
durationMs,
|
|
298
|
-
errorCode,
|
|
299
|
-
idempotencyReplay: false
|
|
300
|
-
}),
|
|
301
|
-
"action.execution"
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
throw executionError;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export { executeActionPipeline };
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { normalizeText } from "./textNormalization.js";
|
|
2
|
-
|
|
3
|
-
const DEFAULT_FIELDS = Object.freeze(["requestId", "commandId", "idempotencyKey", "ip", "userAgent", "request"]);
|
|
4
|
-
|
|
5
|
-
function normalizeRequestMeta(requestMeta = {}, { fields = DEFAULT_FIELDS, emptyAsNull = false } = {}) {
|
|
6
|
-
const source = requestMeta && typeof requestMeta === "object" ? requestMeta : {};
|
|
7
|
-
const fieldList = Array.isArray(fields) && fields.length > 0 ? fields : DEFAULT_FIELDS;
|
|
8
|
-
|
|
9
|
-
const normalizeValue = (value) => {
|
|
10
|
-
const normalized = normalizeText(value);
|
|
11
|
-
if (emptyAsNull && !normalized) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
return normalized;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const normalized = {
|
|
18
|
-
...source
|
|
19
|
-
};
|
|
20
|
-
for (const field of fieldList) {
|
|
21
|
-
if (field === "request") {
|
|
22
|
-
normalized.request = source.request || null;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
if (field === "logger") {
|
|
26
|
-
normalized.logger = source.logger && typeof source.logger.warn === "function" ? source.logger : null;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
normalized[field] = normalizeValue(source[field]);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return normalized;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export { normalizeRequestMeta };
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { normalizeObject } from "../support/normalize.js";
|
|
2
|
-
|
|
3
|
-
function withActionDefaults(actions = [], defaults = {}) {
|
|
4
|
-
const sourceActions = Array.isArray(actions) ? actions : [];
|
|
5
|
-
const sourceDefaults = normalizeObject(defaults);
|
|
6
|
-
const defaultDependencies = normalizeObject(sourceDefaults.dependencies);
|
|
7
|
-
const hasDefaultDependencies = Object.keys(defaultDependencies).length > 0;
|
|
8
|
-
const hasDefaultDomain = Object.hasOwn(sourceDefaults, "domain");
|
|
9
|
-
|
|
10
|
-
return Object.freeze(
|
|
11
|
-
sourceActions.map((entry) => {
|
|
12
|
-
const action = normalizeObject(entry);
|
|
13
|
-
const actionDependencies = normalizeObject(action.dependencies);
|
|
14
|
-
const next = {
|
|
15
|
-
...action
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
if (hasDefaultDomain && !Object.hasOwn(next, "domain")) {
|
|
19
|
-
next.domain = sourceDefaults.domain;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (hasDefaultDependencies || Object.keys(actionDependencies).length > 0) {
|
|
23
|
-
next.dependencies = Object.freeze({
|
|
24
|
-
...defaultDependencies,
|
|
25
|
-
...actionDependencies
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return Object.freeze(next);
|
|
30
|
-
})
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export { withActionDefaults };
|
|
File without changes
|