@classytic/arc 2.31.0 → 2.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/arc.js +58 -17
- package/dist/{BaseController-De7GqHck.mjs → BaseController-CaQC5EXX.mjs} +298 -35
- package/dist/{EventTransport-2uVV34WU.d.mts → EventTransport-BEVP50ka.d.mts} +16 -0
- package/dist/{EventTransport-9mlTgqzE.mjs → EventTransport-tq4CEB-q.mjs} +39 -2
- package/dist/{HookSystem-BcmPyq5I.mjs → HookSystem-DqXkMXkB.mjs} +2 -2
- package/dist/{ResourceRegistry-qq0mn2s9.mjs → ResourceRegistry-DoALUlOO.mjs} +18 -15
- package/dist/{actionPermissions-BE5NwaQk.mjs → actionPermissions-CUeCmpUd.mjs} +1 -1
- package/dist/audit/index.d.mts +2 -2
- package/dist/audit/index.mjs +2 -2
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +2 -2
- package/dist/auth/index.mjs +44 -11
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-ChvUQGG1.mjs → authorizationDecision-B3mP_QTy.mjs} +2 -2
- package/dist/{types-B7XeLEgK.d.mts → base-Csjc2oF-.d.mts} +74 -74
- package/dist/{buildHandler-CDrCJzmB.mjs → buildHandler-DLE9xX-V.mjs} +6 -5
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-BFHA6Scf.mjs → caching-BcGmvnHh.mjs} +2 -2
- package/dist/cleanup/index.d.mts +52 -18
- package/dist/cleanup/index.mjs +281 -32
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +4 -6
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -2
- package/dist/cli/commands/init.mjs +2 -2
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-D3Dv4LAV.mjs → constants-BxCoxmiN.mjs} +1 -1
- package/dist/context/index.mjs +3 -3
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +7 -7
- package/dist/{core-BGpIxINN.mjs → core-dxhcHhUD.mjs} +3 -3
- package/dist/{createActionRouter-CDXEdasl.mjs → createActionRouter-DVpoA0do.mjs} +14 -11
- package/dist/{createAggregationRouter-KrQDzx-k.mjs → createAggregationRouter-B_B48JZ-.mjs} +10 -8
- package/dist/{createApp-Df89BEni.mjs → createApp-CLGegqiG.mjs} +287 -62
- package/dist/{defineAggregation-DbPPS8RI.mjs → defineAggregation-Nv-DwfOf.mjs} +1 -1
- package/dist/{defineResource-Bv6EtN1x.mjs → defineResource-DR9vsUYy.mjs} +318 -35
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +3 -3
- package/dist/{elevation-D2l1mh4g.mjs → elevation-B0tlY8y1.mjs} +4 -4
- package/dist/encryption/index.mjs +5 -4
- package/dist/{errorHandler-C5NeD6bT.mjs → errorHandler-C7xBqHsI.mjs} +42 -5
- package/dist/{errorHandler-CpYUJmPA.d.mts → errorHandler-DI5AN2b5.d.mts} +14 -3
- package/dist/{errors-Cj42AntO.mjs → errors-Cd_yy7aW.mjs} +1 -1
- package/dist/{eventPlugin-GF5nnBIq.d.mts → eventPlugin-DSNEZWfV.d.mts} +29 -1
- package/dist/{eventPlugin-CkffEihm.mjs → eventPlugin-Dar8qRaj.mjs} +68 -11
- package/dist/events/index.d.mts +18 -297
- package/dist/events/index.mjs +7 -758
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +14 -10
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/events/transports/redis.mjs +1 -1
- package/dist/factory/index.d.mts +20 -5
- package/dist/factory/index.mjs +131 -8
- package/dist/fastify-augmentation-DVsTAy6X.d.mts +179 -0
- package/dist/{fields-CB5Cuzk9.mjs → fields-CojeUkS4.mjs} +6 -11
- package/dist/{generate-EcA6ui4i.mjs → generate-DiB0nHPR.mjs} +2 -2
- package/dist/{headers-3zvE0rM3.mjs → headers-CveNO9gR.mjs} +2 -2
- package/dist/{health-DjZYjM7H.mjs → health-CasG2A28.mjs} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +2 -2
- package/dist/idempotency/index.d.mts +45 -1
- package/dist/idempotency/index.mjs +95 -11
- package/dist/idempotency/redis.mjs +1 -1
- package/dist/{index-CEJNZFtX.d.mts → index-B-DvUzsr.d.mts} +82 -3
- package/dist/{index-CpzxqePp.d.mts → index-BcR2bFZQ.d.mts} +707 -373
- package/dist/{index-Bc2ox8_U.d.mts → index-Brin0ODU.d.mts} +4 -4
- package/dist/{index-CFThn1K9.d.mts → index-C5NnMEKF.d.mts} +70 -4
- package/dist/{index-C-481Zf2.d.mts → index-ugr1tQlW.d.mts} +17 -1
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +11 -11
- package/dist/{init-BEiNZBsJ.mjs → init-mdJ-v4Xp.mjs} +24 -16
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +2 -2
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +100 -98
- package/dist/integrations/mcp/index.d.mts +12 -3
- package/dist/integrations/mcp/index.mjs +2 -2
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.mjs +3 -3
- package/dist/integrations/webhooks.d.mts +124 -1
- package/dist/integrations/webhooks.mjs +180 -2
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.mjs +38 -35
- package/dist/{interface-DYzM0q-u.mjs → interface-DznJrm9R.mjs} +1 -1
- package/dist/{jsonBody-BYbLDi5D.mjs → jsonBody-CfGH-GxO.mjs} +2 -2
- package/dist/{keys-C0_pa1tY.mjs → keys-WeKvY1dE.mjs} +1 -1
- package/dist/{loadResources-yawi9tAE.mjs → loadResources-Bj-aSsXi.mjs} +4 -3
- package/dist/{loadResourcesFromEntry-BAjYZonx.mjs → loadResourcesFromEntry-DwaxNcE2.mjs} +2 -2
- package/dist/logger/index.mjs +1 -1
- package/dist/{mcpPlugin-B_es0hiF.mjs → mcpPlugin-aJg5TqHi.mjs} +76 -36
- package/dist/{memory-DR6wpa9F.mjs → memory-qYSB7rMQ.mjs} +5 -5
- package/dist/{metrics-CUdw_wLB.mjs → metrics-D7uchLjN.mjs} +2 -2
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.mjs +3 -3
- package/dist/{module-0pFJA6YW.mjs → module-CwKsgZXp.mjs} +1 -1
- package/dist/{multipartBody-wOgj_fnj.mjs → multipartBody-4w-S3-PU.mjs} +3 -3
- package/dist/{openapi-B2L4js1v.mjs → openapi-BN5cQaO2.mjs} +6 -6
- package/dist/outbox-admin/index.d.mts +85 -0
- package/dist/outbox-admin/index.mjs +115 -0
- package/dist/outbox-module-CXB79bvt.mjs +839 -0
- package/dist/outbox-module-D-VFq37T.d.mts +368 -0
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +6 -6
- package/dist/{permissions-L--QDAir.mjs → permissions-BAfwgBxc.mjs} +120 -8
- package/dist/{pipe-DRDNsI2T.mjs → pipe-BzzoEhHj.mjs} +3 -5
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +2 -2
- package/dist/{pipeline-UPQFatit.mjs → pipeline-q69DZzgG.mjs} +17 -15
- package/dist/plugins/index.d.mts +6 -6
- package/dist/plugins/index.mjs +16 -16
- package/dist/plugins/response-cache.mjs +2 -2
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-O0FZgESl.mjs → pluralize-B7xf8qZF.mjs} +1 -1
- package/dist/{preloadResources-Dz6BjzM6.mjs → preloadResources-BkyqeTDz.mjs} +1 -1
- package/dist/{preloadResources-CyoJMSiO.d.mts → preloadResources-g07ldtzh.d.mts} +30 -7
- package/dist/presets/filesUpload.d.mts +2 -2
- package/dist/presets/filesUpload.mjs +6 -6
- package/dist/presets/index.d.mts +2 -2
- package/dist/presets/index.mjs +2 -2
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +3 -3
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-C4-g4_4P.mjs → presets-D-h0uWtP.mjs} +6 -5
- package/dist/projection-BKM0Ui-s.mjs +42 -0
- package/dist/{queryCachePlugin-BZr8v46E.mjs → queryCachePlugin-DhsZ0ZIc.mjs} +50 -8
- package/dist/{rateLimit-CMPY5Qms.mjs → rateLimit-D4-ASwsI.mjs} +2 -2
- package/dist/{rateLimitKey-Dn5JNmkj.mjs → rateLimitKey-XngqVNEV.mjs} +1 -1
- package/dist/{realtime-C5NoxWFY.mjs → realtime-CTkv3O59.mjs} +10 -10
- package/dist/{redis-stream-qN6A-RFv.d.mts → redis-stream-mwLWlfHG.d.mts} +1 -1
- package/dist/{registerRoute-CBN84fc7.mjs → registerRoute-DNnd3vkz.mjs} +10 -8
- package/dist/registry/index.d.mts +3 -3
- package/dist/registry/index.mjs +3 -3
- package/dist/{registry-4213U4zb.mjs → registry-CLxCR5LF.mjs} +2 -2
- package/dist/{renewingLease-Dll8mGgc.mjs → renewingLease-BnWtbA2U.mjs} +1 -1
- package/dist/{replyHelpers-DIiZKGUt.mjs → replyHelpers-BSBVCwL3.mjs} +2 -2
- package/dist/{repositoryFilter-f9eAfq_l.mjs → repositoryFilter-DKny7PDn.mjs} +1 -1
- package/dist/{requestContext-2TxXOJ7T.mjs → requestContext-uYE35JxI.mjs} +1 -1
- package/dist/{rolldown-runtime-CUsjNX9R.mjs → rolldown-runtime-DNg-KNCk.mjs} +1 -1
- package/dist/runtimeCapabilities-Dm88DaTW.mjs +49 -0
- package/dist/{schedules-DdtlICTf.mjs → schedules-CAcZgia0.mjs} +3 -3
- package/dist/{schemaConverter-D--wdJM-.mjs → schemaConverter-XH1RZRyu.mjs} +1 -1
- package/dist/{schemaIR-Bm2enbnh.mjs → schemaIR-CDvclAew.mjs} +2 -2
- package/dist/schemas/index.mjs +1 -1
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.mjs +5 -5
- package/dist/{scope-DHx5Fous.mjs → scope-BaWcqBvr.mjs} +4 -4
- package/dist/{simpleEqualityMatcher-DjQJ7FKA.mjs → simpleEqualityMatcher-Se8VrsaP.mjs} +1 -1
- package/dist/{sse-CUTo9y0X.mjs → sse-Cf0jUHsh.mjs} +7 -6
- package/dist/{sseStream-B_5XcVVd.mjs → sseStream-Bvpi-UXQ.mjs} +2 -2
- package/dist/{store-helpers-D1MP_gRG.mjs → store-helpers-B88p99Z2.mjs} +1 -1
- package/dist/{streaming-PSZwi8JV.mjs → streaming-DsT1B5zJ.mjs} +1 -1
- package/dist/{subscribe-helpers-C0Tb2aUp.mjs → subscribe-helpers-CLIOHsOK.mjs} +2 -2
- package/dist/sync/changelog.mjs +1 -1
- package/dist/testing/cleanupStoreContract.d.mts +1 -1
- package/dist/testing/cleanupStoreContract.mjs +12 -6
- package/dist/testing/index.d.mts +52 -13
- package/dist/testing/index.mjs +110 -40
- package/dist/testing/outboxStoreContract.d.mts +11 -2
- package/dist/testing/outboxStoreContract.mjs +110 -21
- package/dist/testing/storageContract.mjs +11 -6
- package/dist/{transactionContext-dAfBVUrk.mjs → transactionContext-BYtWnwAS.mjs} +1 -1
- package/dist/{typeGuards-B0ryPo3I.mjs → typeGuards-jjKJDN13.mjs} +1 -1
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-CBgvkp8O.d.mts → types-BcTumAz_.d.mts} +128 -18
- package/dist/{types-CwcUQ610.d.mts → types-BfC83KsP.d.mts} +15 -1
- package/dist/{types-Cys0ko9Z.mjs → types-CoqIRrkY.mjs} +4 -4
- package/dist/{types-C4QE8qnm.d.mts → types-DVLddu2q.d.mts} +144 -1
- package/dist/usage/index.d.mts +1 -1
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-ChYJ6CdK.mjs → userHelpers-CWF5pbZD.mjs} +1 -1
- package/dist/utils/index.d.mts +57 -5
- package/dist/utils/index.mjs +12 -11
- package/dist/{utils-vL8BrDE2.mjs → utils-h1V_sT-t.mjs} +38 -7
- package/dist/{validate-_KbifpHF.mjs → validate-CdQlz52F.mjs} +2 -2
- package/dist/{versioning-D_rhHfZm.d.mts → versioning-DEs-_hFi.d.mts} +1 -1
- package/dist/{versioning-CHDTor3P.mjs → versioning-rZbyLVD-.mjs} +4 -4
- package/package.json +31 -20
- package/skills/arc/SKILL.md +96 -4
- package/skills/arc/references/api-reference.md +19 -0
- package/skills/arc/references/production.md +2 -2
- package/dist/fastify-augmentation-zh0_AYHa.d.mts +0 -85
- package/dist/projection-BHw6xlOQ.mjs +0 -18
package/dist/cleanup/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { g as getUserId } from "../types-
|
|
3
|
-
import { t as defineResource } from "../defineResource-
|
|
4
|
-
import { t as defineModule } from "../module-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { g as getUserId } from "../types-CoqIRrkY.mjs";
|
|
3
|
+
import { t as defineResource } from "../defineResource-DR9vsUYy.mjs";
|
|
4
|
+
import { t as defineModule } from "../module-CwKsgZXp.mjs";
|
|
5
5
|
import { createPurgeEvidence } from "@classytic/primitives/retention";
|
|
6
6
|
import { canonicalJson, sha256Hex } from "@classytic/primitives/canonical";
|
|
7
7
|
//#region src/cleanup/errors.ts
|
|
@@ -85,6 +85,18 @@ const CleanupErrors = {
|
|
|
85
85
|
status
|
|
86
86
|
});
|
|
87
87
|
},
|
|
88
|
+
/**
|
|
89
|
+
* The operator's exclusion list cannot be honoured as written.
|
|
90
|
+
*
|
|
91
|
+
* A 400 rather than a filter: dropping an unrecognised exclusion leaves
|
|
92
|
+
* someone believing they narrowed a destructive run when they did not, and
|
|
93
|
+
* dropping a PROTECTIVE one would let a guard be switched off from the same
|
|
94
|
+
* request that starts the run. `steps` carries the offending ids so a UI can
|
|
95
|
+
* point at them.
|
|
96
|
+
*/
|
|
97
|
+
invalidExclusion(reason, steps) {
|
|
98
|
+
return new CleanupError("CLEANUP_INVALID_EXCLUSION", 400, reason, { steps: [...steps] });
|
|
99
|
+
},
|
|
88
100
|
forbidden(operation) {
|
|
89
101
|
return new CleanupError("CLEANUP_FORBIDDEN", 403, `Not authorized to ${operation} cleanup.`, { operation });
|
|
90
102
|
}
|
|
@@ -102,6 +114,53 @@ function stepContextOf(ctx, parameters) {
|
|
|
102
114
|
logger: ctx.logger
|
|
103
115
|
};
|
|
104
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Resolve the operator's exclusion list against the recipe's real steps.
|
|
119
|
+
*
|
|
120
|
+
* REFUSES rather than filters. Two rejections, both of which a permissive
|
|
121
|
+
* version would turn into a silent lie:
|
|
122
|
+
*
|
|
123
|
+
* - **unknown id** — a typo, or a step that has since been removed. Dropping
|
|
124
|
+
* it leaves the operator believing they narrowed a destructive run when the
|
|
125
|
+
* excluded domain will in fact be purged. A free-text ignore-list that
|
|
126
|
+
* silently tolerates unknown entries carries exactly this hazard.
|
|
127
|
+
* - **a protective step** — the property an ignore-list alone cannot give. A
|
|
128
|
+
* guard deletes nothing; it stands between the run and records that must
|
|
129
|
+
* never be purged. If it can be switched off from the same screen that
|
|
130
|
+
* starts the run, it is advice, not a guard. `destructive: false` alone is
|
|
131
|
+
* not the test — a projection rebuild is also non-destructive and IS
|
|
132
|
+
* legitimately excludable — so the marker is the step's own
|
|
133
|
+
* `disposition: 'protect'`.
|
|
134
|
+
*
|
|
135
|
+
* Returns the validated set; throws `CleanupErrors.invalidInput` otherwise.
|
|
136
|
+
*/
|
|
137
|
+
function resolveExclusions(steps, requested) {
|
|
138
|
+
if (!requested || requested.length === 0) return /* @__PURE__ */ new Set();
|
|
139
|
+
const byId = new Map(steps.map((s) => [s.id, s]));
|
|
140
|
+
const unknown = [];
|
|
141
|
+
const protectedIds = [];
|
|
142
|
+
for (const id of requested) {
|
|
143
|
+
const step = byId.get(id);
|
|
144
|
+
if (!step) {
|
|
145
|
+
unknown.push(id);
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (isProtective(step)) protectedIds.push(id);
|
|
149
|
+
}
|
|
150
|
+
if (unknown.length > 0) throw CleanupErrors.invalidExclusion(`excludeSteps names step(s) this recipe does not have: ${unknown.join(", ")}. Refusing rather than ignoring — a dropped exclusion means the run touches data the operator believed they had left out.`, unknown);
|
|
151
|
+
if (protectedIds.length > 0) throw CleanupErrors.invalidExclusion(`excludeSteps names protective step(s): ${protectedIds.join(", ")}. A guard deletes nothing; it refuses the run when records that must never be purged are present. It cannot be switched off from the same request that starts the run.`, protectedIds);
|
|
152
|
+
return new Set(requested);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Is this step a GUARD?
|
|
156
|
+
*
|
|
157
|
+
* Asked of the step's declared disposition rather than `destructive`, because
|
|
158
|
+
* `destructive: false` covers guards AND projection rebuilds — and a rebuild is
|
|
159
|
+
* perfectly reasonable to exclude.
|
|
160
|
+
*/
|
|
161
|
+
function isProtective(step) {
|
|
162
|
+
return step.disposition === "protect";
|
|
163
|
+
}
|
|
105
164
|
function errMessage(err) {
|
|
106
165
|
return err instanceof Error ? err.message : String(err);
|
|
107
166
|
}
|
|
@@ -131,16 +190,63 @@ function recipeFromSteps(input) {
|
|
|
131
190
|
},
|
|
132
191
|
async plan(cleanupInput, ctx) {
|
|
133
192
|
const stepCtx = stepContextOf(ctx, cleanupInput.parameters ?? {});
|
|
193
|
+
const excluded = resolveExclusions(steps, cleanupInput.excludeSteps);
|
|
134
194
|
const items = [];
|
|
135
195
|
const blockers = /* @__PURE__ */ new Set();
|
|
136
196
|
const retains = new Set(input.retains ?? []);
|
|
137
197
|
const rebuildActions = /* @__PURE__ */ new Set();
|
|
138
198
|
const warnings = new Set(input.warnings ?? []);
|
|
139
199
|
for (const step of steps) {
|
|
200
|
+
/**
|
|
201
|
+
* An excluded step is NOT estimated.
|
|
202
|
+
*
|
|
203
|
+
* Estimating it would run its counting queries for a line the operator
|
|
204
|
+
* has already taken out — cost with no consequence — and, worse, would
|
|
205
|
+
* surface its blockers, so leaving a domain out of a run could still be
|
|
206
|
+
* refused because of that domain. A line the run will not touch must not
|
|
207
|
+
* be able to stop the run.
|
|
208
|
+
*/
|
|
209
|
+
if (excluded.has(step.id)) {
|
|
210
|
+
items.push({
|
|
211
|
+
stepId: step.id,
|
|
212
|
+
resource: step.resource,
|
|
213
|
+
estimated: 0,
|
|
214
|
+
excluded: true,
|
|
215
|
+
retained: "excluded from this run by the operator"
|
|
216
|
+
});
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
140
219
|
const est = await step.estimate(stepCtx);
|
|
220
|
+
/**
|
|
221
|
+
* Disposition comes from the STEP, not from `step.destructive`.
|
|
222
|
+
*
|
|
223
|
+
* (See the exclusion handling above for why `'protect'` also decides
|
|
224
|
+
* whether a line may be left out of a run.)
|
|
225
|
+
*
|
|
226
|
+
* They are close but not the same, and conflating them is how the bug
|
|
227
|
+
* this fixes arose. `destructive: false` covers BOTH a protective guard
|
|
228
|
+
* (counts what it defends) and a projection rebuild (counts what it
|
|
229
|
+
* recomputes) — opposite meanings for the headline. A step that says
|
|
230
|
+
* nothing means `'remove'`, which is what every purge step is.
|
|
231
|
+
*/
|
|
232
|
+
/**
|
|
233
|
+
* A step may only PROTECT if it said so on the step itself.
|
|
234
|
+
*
|
|
235
|
+
* `resolveExclusions` runs before any estimate — it has to, since it
|
|
236
|
+
* decides which steps to estimate at all — so it can read only
|
|
237
|
+
* `step.disposition`. A guard that declared `'protect'` from its
|
|
238
|
+
* ESTIMATE instead was therefore excludable: the plan line came back
|
|
239
|
+
* marked protective, looked defended, and `excludeSteps: [thatId]`
|
|
240
|
+
* still switched it off. That is precisely the property this feature
|
|
241
|
+
* exists to make impossible, so the mismatch is an authoring error
|
|
242
|
+
* rather than a silent downgrade.
|
|
243
|
+
*/
|
|
244
|
+
if (est.disposition === "protect" && step.disposition !== "protect") throw CleanupErrors.invalidExclusion(`step '${step.id}' returned disposition 'protect' from its estimate but does not declare \`disposition: 'protect'\` on the step. Exclusions are resolved before estimates run, so a guard declared only at estimate time can be excluded — switching off the check it exists to enforce. Declare it on the step.`, [step.id]);
|
|
141
245
|
items.push({
|
|
246
|
+
stepId: step.id,
|
|
142
247
|
resource: est.resource,
|
|
143
248
|
estimated: est.estimated,
|
|
249
|
+
...(est.disposition ?? step.disposition) !== void 0 ? { disposition: est.disposition ?? step.disposition } : {},
|
|
144
250
|
...est.retained !== void 0 ? { retained: est.retained } : {},
|
|
145
251
|
...est.blockers && est.blockers.length > 0 ? { blockers: est.blockers } : {}
|
|
146
252
|
});
|
|
@@ -161,8 +267,44 @@ function recipeFromSteps(input) {
|
|
|
161
267
|
async execute(plan, ctx) {
|
|
162
268
|
const parameters = plan.parameters ?? {};
|
|
163
269
|
const results = [];
|
|
270
|
+
/**
|
|
271
|
+
* Re-resolved from the SEALED plan, never from a fresh caller input.
|
|
272
|
+
*
|
|
273
|
+
* The exclusion set is part of the digest the operator confirmed against,
|
|
274
|
+
* so taking it from the plan is what makes consent binding: an execute
|
|
275
|
+
* cannot widen the run beyond what was previewed. Re-validating here also
|
|
276
|
+
* means a step that has since become protective refuses rather than being
|
|
277
|
+
* quietly dropped.
|
|
278
|
+
*/
|
|
279
|
+
const excluded = resolveExclusions(steps, plan.excludeSteps);
|
|
280
|
+
/**
|
|
281
|
+
* Lifecycle reporting is OPTIONAL on the context — a host service that
|
|
282
|
+
* predates it simply gets no per-step view, rather than a crash. Resolved
|
|
283
|
+
* once so the loop below reads as bookkeeping, not feature detection.
|
|
284
|
+
*/
|
|
285
|
+
const reportState = ctx.onStepState?.bind(ctx) ?? (async () => {});
|
|
164
286
|
for (const step of steps) {
|
|
165
287
|
await ctx.throwIfCancelled();
|
|
288
|
+
if (excluded.has(step.id)) {
|
|
289
|
+
await reportState({
|
|
290
|
+
stepId: step.id,
|
|
291
|
+
resource: step.resource,
|
|
292
|
+
status: "skipped",
|
|
293
|
+
processed: 0,
|
|
294
|
+
startedAt: ctx.now,
|
|
295
|
+
completedAt: ctx.now,
|
|
296
|
+
detail: "excluded by the operator"
|
|
297
|
+
});
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
const startedAt = ctx.now;
|
|
301
|
+
await reportState({
|
|
302
|
+
stepId: step.id,
|
|
303
|
+
resource: step.resource,
|
|
304
|
+
status: "running",
|
|
305
|
+
processed: 0,
|
|
306
|
+
startedAt
|
|
307
|
+
});
|
|
166
308
|
let reported = 0;
|
|
167
309
|
const execCtx = {
|
|
168
310
|
...stepContextOf(ctx, parameters),
|
|
@@ -211,6 +353,25 @@ function recipeFromSteps(input) {
|
|
|
211
353
|
...outcome.error !== void 0 ? { error: outcome.error } : {},
|
|
212
354
|
...outcome.cursor !== void 0 ? { cursor: outcome.cursor } : {}
|
|
213
355
|
});
|
|
356
|
+
/**
|
|
357
|
+
* `skipped` is a REAL outcome, not "completed with zero".
|
|
358
|
+
*
|
|
359
|
+
* A step that had nothing in scope and a step that removed 4,000 rows
|
|
360
|
+
* both end `ok`, and reading a bare 0 as success is how an operator
|
|
361
|
+
* concludes a phase ran when its scope was simply empty. Three states
|
|
362
|
+
* alone only CATEGORISE the outcome; the `detail` is what makes it
|
|
363
|
+
* answerable.
|
|
364
|
+
*/
|
|
365
|
+
const isSkip = outcome.ok && outcome.processed === 0;
|
|
366
|
+
await reportState({
|
|
367
|
+
stepId: step.id,
|
|
368
|
+
resource: outcome.resource,
|
|
369
|
+
status: outcome.ok ? isSkip ? "skipped" : "completed" : "failed",
|
|
370
|
+
processed: outcome.processed,
|
|
371
|
+
startedAt,
|
|
372
|
+
completedAt: ctx.now,
|
|
373
|
+
...outcome.ok ? isSkip ? { detail: "nothing in scope" } : {} : { detail: outcome.error ?? "step failed" }
|
|
374
|
+
});
|
|
214
375
|
if (!outcome.ok) break;
|
|
215
376
|
}
|
|
216
377
|
const allOk = results.every((r) => r.ok);
|
|
@@ -465,12 +626,15 @@ function planMaterial(plan) {
|
|
|
465
626
|
items: plan.items.map((i) => ({
|
|
466
627
|
resource: i.resource,
|
|
467
628
|
estimated: i.estimated,
|
|
629
|
+
disposition: i.disposition ?? "remove",
|
|
630
|
+
excluded: i.excluded ?? false,
|
|
468
631
|
retained: i.retained ?? null,
|
|
469
632
|
blockers: [...i.blockers ?? []].sort()
|
|
470
633
|
})).sort((a, b) => a.resource < b.resource ? -1 : a.resource > b.resource ? 1 : a.estimated - b.estimated),
|
|
471
634
|
retains: [...plan.retains].sort(),
|
|
472
635
|
blockers: [...plan.blockers].sort(),
|
|
473
636
|
rebuildActions: [...plan.rebuildActions].sort(),
|
|
637
|
+
excludeSteps: [...plan.excludeSteps].sort(),
|
|
474
638
|
estimatedTotal: plan.estimatedTotal,
|
|
475
639
|
confirmationPhrase: plan.confirmationPhrase
|
|
476
640
|
};
|
|
@@ -563,7 +727,7 @@ function createCleanupService(deps) {
|
|
|
563
727
|
...DEFAULT_CLEANUP_LIMITS,
|
|
564
728
|
...deps.limits
|
|
565
729
|
};
|
|
566
|
-
const leaseMs = deps.leaseMs ??
|
|
730
|
+
const leaseMs = deps.leaseMs ?? 3e5;
|
|
567
731
|
const progressThrottleMs = deps.progressThrottleMs ?? 0;
|
|
568
732
|
const jobQueue = deps.jobQueue ?? { enqueue: async (job) => {
|
|
569
733
|
queueMicrotask(() => {
|
|
@@ -586,10 +750,22 @@ function createCleanupService(deps) {
|
|
|
586
750
|
};
|
|
587
751
|
}
|
|
588
752
|
async function seal(recipe, input, ctx) {
|
|
589
|
-
const draft = await recipe.plan({
|
|
753
|
+
const draft = await recipe.plan({
|
|
754
|
+
parameters: input.parameters,
|
|
755
|
+
excludeSteps: input.excludeSteps
|
|
756
|
+
}, ctx);
|
|
590
757
|
const items = draft.items;
|
|
591
758
|
if (items.length > limits.maxPlanItems) throw CleanupErrors.planTooLarge(`${items.length} items > maxPlanItems ${limits.maxPlanItems}`);
|
|
592
|
-
|
|
759
|
+
/**
|
|
760
|
+
* Partition by DISPOSITION — a protective guard's count is not damage.
|
|
761
|
+
*
|
|
762
|
+
* This was one `reduce` over every item, so a guard reporting the 173 posted
|
|
763
|
+
* journal entries it defends pushed the "records to remove" headline to 540
|
|
764
|
+
* on a plan that removes 367. Absent disposition means `'remove'`, so every
|
|
765
|
+
* pre-existing recipe is unchanged.
|
|
766
|
+
*/
|
|
767
|
+
const estimatedTotal = items.reduce((sum, i) => sum + ((i.disposition ?? "remove") === "remove" ? i.estimated : 0), 0);
|
|
768
|
+
const protectedTotal = items.reduce((sum, i) => sum + (i.disposition === "protect" ? i.estimated : 0), 0);
|
|
593
769
|
const blockers = new Set(draft.blockers ?? []);
|
|
594
770
|
for (const item of items) for (const b of item.blockers ?? []) blockers.add(b);
|
|
595
771
|
const unsealed = {
|
|
@@ -601,6 +777,8 @@ function createCleanupService(deps) {
|
|
|
601
777
|
rebuildActions: [...draft.rebuildActions ?? []],
|
|
602
778
|
warnings: [...draft.warnings ?? []],
|
|
603
779
|
estimatedTotal,
|
|
780
|
+
protectedTotal,
|
|
781
|
+
excludeSteps: [...input.excludeSteps ?? []].sort(),
|
|
604
782
|
confirmationPhrase: draft.confirmationPhrase ?? recipe.id
|
|
605
783
|
};
|
|
606
784
|
return {
|
|
@@ -713,6 +891,14 @@ function createCleanupService(deps) {
|
|
|
713
891
|
let processed = 0;
|
|
714
892
|
let steps = 0;
|
|
715
893
|
let failed = 0;
|
|
894
|
+
/**
|
|
895
|
+
* Per-step lifecycle, keyed by `stepId` and ordered by first sight.
|
|
896
|
+
*
|
|
897
|
+
* Seeded from the run's existing progress so a RESUMED run (crash recovery,
|
|
898
|
+
* retry) keeps the states it already recorded instead of presenting an
|
|
899
|
+
* operator with a blank pipeline for work that demonstrably happened.
|
|
900
|
+
*/
|
|
901
|
+
const stepStates = new Map((run.progress?.stepProgress ?? []).map((s) => [s.stepId, s]));
|
|
716
902
|
let cancelled = false;
|
|
717
903
|
let lastSummary = run.progress ?? EMPTY_PROGRESS;
|
|
718
904
|
let lastPersistMs = 0;
|
|
@@ -745,6 +931,7 @@ function createCleanupService(deps) {
|
|
|
745
931
|
steps,
|
|
746
932
|
failed,
|
|
747
933
|
currentResource: step.resource,
|
|
934
|
+
...stepStates.size > 0 ? { stepProgress: [...stepStates.values()] } : {},
|
|
748
935
|
...step.cursor !== void 0 ? { lastCursor: step.cursor } : {},
|
|
749
936
|
heartbeatAt: now()
|
|
750
937
|
};
|
|
@@ -756,6 +943,31 @@ function createCleanupService(deps) {
|
|
|
756
943
|
await refreshCancel();
|
|
757
944
|
}
|
|
758
945
|
},
|
|
946
|
+
/**
|
|
947
|
+
* Upsert one step's lifecycle state, preserving FIRST-SEEN order.
|
|
948
|
+
*
|
|
949
|
+
* A `Map` keyed by `stepId` is what keeps this bounded and idempotent: a
|
|
950
|
+
* step transitioning running → completed updates its entry rather than
|
|
951
|
+
* appending, so the array length is the step count and never the
|
|
952
|
+
* transition count. Insertion order is the execution order, which is what
|
|
953
|
+
* an operator reads down the list.
|
|
954
|
+
*
|
|
955
|
+
* Persisted on the NEXT `onStep` (or the terminal write) rather than
|
|
956
|
+
* immediately — a lifecycle transition is not itself a committed chunk,
|
|
957
|
+
* and writing on every one would defeat the progress throttle that exists
|
|
958
|
+
* to keep a long run from hammering the store.
|
|
959
|
+
*/
|
|
960
|
+
async onStepState(state) {
|
|
961
|
+
stepStates.set(state.stepId, state);
|
|
962
|
+
lastSummary = {
|
|
963
|
+
...lastSummary ?? {
|
|
964
|
+
processed,
|
|
965
|
+
steps,
|
|
966
|
+
failed
|
|
967
|
+
},
|
|
968
|
+
stepProgress: [...stepStates.values()]
|
|
969
|
+
};
|
|
970
|
+
},
|
|
759
971
|
async throwIfCancelled() {
|
|
760
972
|
if (cancelled || controller.signal.aborted || await refreshCancel()) throw new CleanupCancelled(run.id);
|
|
761
973
|
}
|
|
@@ -1079,13 +1291,31 @@ const parametersSchema = {
|
|
|
1079
1291
|
type: "object",
|
|
1080
1292
|
additionalProperties: true
|
|
1081
1293
|
};
|
|
1294
|
+
/**
|
|
1295
|
+
* Step ids to leave out. Bounded and unique — an unbounded list on a
|
|
1296
|
+
* destructive endpoint is a denial-of-service surface, and a duplicate id says
|
|
1297
|
+
* nothing a single one does not. Unknown or PROTECTIVE ids are refused by the
|
|
1298
|
+
* recipe (CLEANUP_INVALID_EXCLUSION), not stripped here: the route must not
|
|
1299
|
+
* decide what an operator may narrow.
|
|
1300
|
+
*/
|
|
1301
|
+
const excludeStepsSchema = {
|
|
1302
|
+
type: "array",
|
|
1303
|
+
items: {
|
|
1304
|
+
type: "string",
|
|
1305
|
+
minLength: 1,
|
|
1306
|
+
maxLength: 200
|
|
1307
|
+
},
|
|
1308
|
+
maxItems: 200,
|
|
1309
|
+
uniqueItems: true
|
|
1310
|
+
};
|
|
1082
1311
|
const previewBodySchema = {
|
|
1083
1312
|
type: "object",
|
|
1084
1313
|
required: ["recipe"],
|
|
1085
1314
|
additionalProperties: false,
|
|
1086
1315
|
properties: {
|
|
1087
1316
|
recipe: recipeIdSchema,
|
|
1088
|
-
parameters: parametersSchema
|
|
1317
|
+
parameters: parametersSchema,
|
|
1318
|
+
excludeSteps: excludeStepsSchema
|
|
1089
1319
|
}
|
|
1090
1320
|
};
|
|
1091
1321
|
const runsBodySchema = {
|
|
@@ -1099,6 +1329,7 @@ const runsBodySchema = {
|
|
|
1099
1329
|
properties: {
|
|
1100
1330
|
recipe: recipeIdSchema,
|
|
1101
1331
|
parameters: parametersSchema,
|
|
1332
|
+
excludeSteps: excludeStepsSchema,
|
|
1102
1333
|
planDigest: {
|
|
1103
1334
|
type: "string",
|
|
1104
1335
|
minLength: 1,
|
|
@@ -1140,24 +1371,40 @@ const actionBodySchema = {
|
|
|
1140
1371
|
}
|
|
1141
1372
|
}
|
|
1142
1373
|
};
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
*/
|
|
1374
|
+
async function resolve(input) {
|
|
1375
|
+
return typeof input === "function" ? await input() : input;
|
|
1376
|
+
}
|
|
1147
1377
|
function createDataCleanupModule(deps) {
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1378
|
+
/**
|
|
1379
|
+
* Built on FIRST READ, which is `bootstrap` — never in this factory body.
|
|
1380
|
+
*
|
|
1381
|
+
* Memoized, so the recipe thunk runs exactly once and the id-uniqueness check
|
|
1382
|
+
* still happens at boot (arc calls bootstrap during startup); it simply happens
|
|
1383
|
+
* inside arc's lifecycle rather than ahead of it.
|
|
1384
|
+
*/
|
|
1385
|
+
let cachedRegistry;
|
|
1386
|
+
const registry = async () => {
|
|
1387
|
+
cachedRegistry ??= createCleanupRegistry(typeof deps.recipes === "function" ? await deps.recipes() : deps.recipes);
|
|
1388
|
+
return cachedRegistry;
|
|
1389
|
+
};
|
|
1390
|
+
if (typeof deps.recipes !== "function") cachedRegistry = createCleanupRegistry(deps.recipes);
|
|
1391
|
+
let cached;
|
|
1392
|
+
const service = async () => {
|
|
1393
|
+
if (cached) return cached;
|
|
1394
|
+
cached = createCleanupService({
|
|
1395
|
+
registry: await registry(),
|
|
1396
|
+
runStore: await resolve(deps.runStore),
|
|
1397
|
+
evidenceStore: await resolve(deps.evidenceStore),
|
|
1398
|
+
writeFence: await resolve(deps.writeFence),
|
|
1399
|
+
jobQueue: await resolve(deps.jobQueue),
|
|
1400
|
+
limits: deps.limits,
|
|
1401
|
+
leaseMs: deps.leaseMs,
|
|
1402
|
+
progressThrottleMs: deps.progressThrottleMs,
|
|
1403
|
+
generateId: deps.generateId,
|
|
1404
|
+
now: deps.now
|
|
1405
|
+
});
|
|
1406
|
+
return cached;
|
|
1407
|
+
};
|
|
1161
1408
|
const prefix = deps.prefix ?? "/governance/data-cleanup";
|
|
1162
1409
|
const resolveActor = deps.resolveActor ?? defaultResolveActor;
|
|
1163
1410
|
const resolveAmbient = deps.resolveAmbient;
|
|
@@ -1177,7 +1424,7 @@ function createDataCleanupModule(deps) {
|
|
|
1177
1424
|
summary: "List available cleanup recipes",
|
|
1178
1425
|
permissions: view,
|
|
1179
1426
|
rawHandler: async (_req, reply) => {
|
|
1180
|
-
return reply.send({ recipes: registry.introspect() });
|
|
1427
|
+
return reply.send({ recipes: (await registry()).introspect() });
|
|
1181
1428
|
}
|
|
1182
1429
|
},
|
|
1183
1430
|
{
|
|
@@ -1189,9 +1436,10 @@ function createDataCleanupModule(deps) {
|
|
|
1189
1436
|
rawHandler: async (req, reply) => {
|
|
1190
1437
|
const r = req;
|
|
1191
1438
|
const body = req.body;
|
|
1192
|
-
const plan = await service.preview({
|
|
1439
|
+
const plan = await (await service()).preview({
|
|
1193
1440
|
recipeId: body.recipe,
|
|
1194
1441
|
parameters: body.parameters,
|
|
1442
|
+
excludeSteps: body.excludeSteps,
|
|
1195
1443
|
actor: resolveActor(r),
|
|
1196
1444
|
ambient: resolveAmbient?.(r)
|
|
1197
1445
|
});
|
|
@@ -1207,9 +1455,10 @@ function createDataCleanupModule(deps) {
|
|
|
1207
1455
|
rawHandler: async (req, reply) => {
|
|
1208
1456
|
const r = req;
|
|
1209
1457
|
const body = req.body;
|
|
1210
|
-
const run = await service.execute({
|
|
1458
|
+
const run = await (await service()).execute({
|
|
1211
1459
|
recipeId: body.recipe,
|
|
1212
1460
|
parameters: body.parameters,
|
|
1461
|
+
excludeSteps: body.excludeSteps,
|
|
1213
1462
|
planDigest: body.planDigest,
|
|
1214
1463
|
reason: body.reason,
|
|
1215
1464
|
confirmation: body.confirmation,
|
|
@@ -1227,7 +1476,7 @@ function createDataCleanupModule(deps) {
|
|
|
1227
1476
|
schema: { params: runIdParamsSchema },
|
|
1228
1477
|
rawHandler: async (req, reply) => {
|
|
1229
1478
|
const { id } = req.params;
|
|
1230
|
-
return reply.send(await service.getRun(id));
|
|
1479
|
+
return reply.send(await (await service()).getRun(id));
|
|
1231
1480
|
}
|
|
1232
1481
|
},
|
|
1233
1482
|
{
|
|
@@ -1243,11 +1492,11 @@ function createDataCleanupModule(deps) {
|
|
|
1243
1492
|
const actionActor = resolveActor(req);
|
|
1244
1493
|
const { id } = req.params;
|
|
1245
1494
|
const { action, reason } = req.body;
|
|
1246
|
-
if (action === "cancel") return reply.send(await service.cancel(id, {
|
|
1495
|
+
if (action === "cancel") return reply.send(await (await service()).cancel(id, {
|
|
1247
1496
|
actor: actionActor,
|
|
1248
1497
|
reason
|
|
1249
1498
|
}));
|
|
1250
|
-
return reply.send(await service.retry(id));
|
|
1499
|
+
return reply.send(await (await service()).retry(id));
|
|
1251
1500
|
}
|
|
1252
1501
|
}
|
|
1253
1502
|
]
|
|
@@ -1255,7 +1504,7 @@ function createDataCleanupModule(deps) {
|
|
|
1255
1504
|
return defineModule({
|
|
1256
1505
|
name: deps.moduleName ?? "data-cleanup",
|
|
1257
1506
|
...deps.owns ? { owns: deps.owns } : {},
|
|
1258
|
-
bootstrap: () => service,
|
|
1507
|
+
bootstrap: () => service(),
|
|
1259
1508
|
resources: () => [resource]
|
|
1260
1509
|
});
|
|
1261
1510
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { Nt as RateLimitConfig, V as ResourceDefinition, et as RouteSchemaOptions } from "../../index-
|
|
2
|
+
import { Nt as RateLimitConfig, V as ResourceDefinition, et as RouteSchemaOptions } from "../../index-BcR2bFZQ.mjs";
|
|
3
3
|
//#region src/cli/commands/describe.d.ts
|
|
4
4
|
interface DescribedResource {
|
|
5
5
|
name: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as CRUD_OPERATIONS } from "../../constants-
|
|
3
|
-
import { n as stringifyMeasureMap } from "../../ResourceRegistry-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as CRUD_OPERATIONS } from "../../constants-BxCoxmiN.mjs";
|
|
3
|
+
import { n as stringifyMeasureMap } from "../../ResourceRegistry-DoALUlOO.mjs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
//#region src/cli/commands/describe.ts
|
|
@@ -78,9 +78,7 @@ function describePipeline(pipe) {
|
|
|
78
78
|
case "transform":
|
|
79
79
|
transforms.push(desc);
|
|
80
80
|
break;
|
|
81
|
-
case "interceptor":
|
|
82
|
-
interceptors.push(desc);
|
|
83
|
-
break;
|
|
81
|
+
case "interceptor": interceptors.push(desc);
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as buildOpenApiSpec } from "../../openapi-
|
|
3
|
-
import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as buildOpenApiSpec } from "../../openapi-BN5cQaO2.mjs";
|
|
3
|
+
import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-DwaxNcE2.mjs";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
6
6
|
//#region src/cli/commands/docs.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
2
|
import { dirname, join, parse, resolve } from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
//#region src/cli/commands/doctor.ts
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as generate } from "../../generate-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as generate } from "../../generate-DiB0nHPR.mjs";
|
|
3
3
|
export { generate };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as init } from "../../init-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as init } from "../../init-mdJ-v4Xp.mjs";
|
|
3
3
|
export { init };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-DwaxNcE2.mjs";
|
|
3
3
|
//#region src/cli/commands/introspect.ts
|
|
4
4
|
function describePermission(value) {
|
|
5
5
|
if (!value) return "none";
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
2
|
import { describe } from "./commands/describe.mjs";
|
|
3
3
|
import { exportDocs } from "./commands/docs.mjs";
|
|
4
4
|
import { doctor } from "./commands/doctor.mjs";
|
|
5
|
-
import { t as generate } from "../generate-
|
|
6
|
-
import { t as init } from "../init-
|
|
5
|
+
import { t as generate } from "../generate-DiB0nHPR.mjs";
|
|
6
|
+
import { t as init } from "../init-mdJ-v4Xp.mjs";
|
|
7
7
|
import { introspect } from "./commands/introspect.mjs";
|
|
8
8
|
export { describe, doctor, exportDocs, generate, init, introspect };
|
package/dist/context/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { n as requestContext, t as getTraceHeaders } from "../requestContext-
|
|
3
|
-
import { t as transactionContext } from "../transactionContext-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as requestContext, t as getTraceHeaders } from "../requestContext-uYE35JxI.mjs";
|
|
3
|
+
import { t as transactionContext } from "../transactionContext-BYtWnwAS.mjs";
|
|
4
4
|
export { getTraceHeaders, requestContext, transactionContext };
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
import { $t as
|
|
3
|
-
import { A as DEFAULT_ID_FIELD, B as MAX_FILTER_DEPTH, C as DefineActionConfig, D as defineAggregation, E as createPermissionMiddleware, F as DEFAULT_UPDATE_METHOD, G as RESERVED_QUERY_PARAMS, H as MAX_SEARCH_LENGTH, I as HOOK_OPERATIONS, K as SYSTEM_FIELDS, L as HOOK_PHASES, M as DEFAULT_MAX_LIMIT, N as DEFAULT_SORT, O as CRUD_OPERATIONS, P as DEFAULT_TENANT_FIELD, R as HookOperation, S as mergeResourceConfig, T as createCrudRouter, U as MUTATION_OPERATIONS, V as MAX_REGEX_LENGTH, W as MutationOperation, _ as getEntityQuery, a as formatValidationErrors, b as ResourceSeams, c as isFieldReadable, d as createRequestContext, f as getControllerContext, g as getEntityIdField, h as getEntityId, i as assertValidConfig, j as DEFAULT_LIMIT, k as CrudOperation, l as createCrudHandlers, m as sendControllerResponse, n as ValidateOptions, o as validateResourceConfig, p as getControllerScope, r as ValidationResult, s as collectReadBlockedFields, t as ConfigError, u as createFastifyHandler, v as defineResourceVariants, w as defineAction, x as SeamedResourceConfig, y as AdapterLike, z as HookPhase } from "../index-
|
|
2
|
+
import { $t as AccessControlConfig, B as defineResource, Bt as BaseController, Cn as ControllerConstructionOptions, En as BodySanitizerConfig, Gt as SlugExt, Ht as SoftDeleteMixin, Jt as BulkMixin, Kt as SlugMixin, Qt as AccessControl, Sn as ControllerConfigurableOptions, Tn as BodySanitizer, Ut as TreeExt, V as ResourceDefinition, Vt as SoftDeleteExt, Wt as TreeMixin, Xt as QueryResolver, Yt as BaseCrudController, Zt as QueryResolverConfig, ct as AggMeasureShorthand, dt as AggregationDateRangeRequirement, ft as AggregationIndexHint, gt as AggregationsMap, ht as AggregationRateLimit, lt as AggregationCacheConfig, mt as AggregationMaterializedResult, pt as AggregationMaterializedContext, qt as BulkExt, st as AggMeasureInput, ut as AggregationConfig, wn as ListResult, xn as BaseControllerOptions } from "../index-BcR2bFZQ.mjs";
|
|
3
|
+
import { A as DEFAULT_ID_FIELD, B as MAX_FILTER_DEPTH, C as DefineActionConfig, D as defineAggregation, E as createPermissionMiddleware, F as DEFAULT_UPDATE_METHOD, G as RESERVED_QUERY_PARAMS, H as MAX_SEARCH_LENGTH, I as HOOK_OPERATIONS, K as SYSTEM_FIELDS, L as HOOK_PHASES, M as DEFAULT_MAX_LIMIT, N as DEFAULT_SORT, O as CRUD_OPERATIONS, P as DEFAULT_TENANT_FIELD, R as HookOperation, S as mergeResourceConfig, T as createCrudRouter, U as MUTATION_OPERATIONS, V as MAX_REGEX_LENGTH, W as MutationOperation, _ as getEntityQuery, a as formatValidationErrors, b as ResourceSeams, c as isFieldReadable, d as createRequestContext, f as getControllerContext, g as getEntityIdField, h as getEntityId, i as assertValidConfig, j as DEFAULT_LIMIT, k as CrudOperation, l as createCrudHandlers, m as sendControllerResponse, n as ValidateOptions, o as validateResourceConfig, p as getControllerScope, r as ValidationResult, s as collectReadBlockedFields, t as ConfigError, u as createFastifyHandler, v as defineResourceVariants, w as defineAction, x as SeamedResourceConfig, y as AdapterLike, z as HookPhase } from "../index-Brin0ODU.mjs";
|
|
4
4
|
export { AccessControl, type AccessControlConfig, type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, BaseController, type BaseControllerOptions, BaseCrudController, BodySanitizer, type BodySanitizerConfig, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DefineActionConfig, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, type QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, type ResourceSeams, SYSTEM_FIELDS, type SeamedResourceConfig, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type ValidateOptions, type ValidationResult, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, sendControllerResponse, validateResourceConfig };
|
package/dist/core/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-
|
|
3
|
-
import { a as BulkMixin, c as collectReadBlockedFields, f as
|
|
4
|
-
import { a as ResourceDefinition, i as validateResourceConfig, n as assertValidConfig, o as createCrudRouter, r as formatValidationErrors, s as createPermissionMiddleware, t as defineResource } from "../defineResource-
|
|
5
|
-
import { a as createFastifyHandler, c as getControllerScope, i as createCrudHandlers, l as sendControllerResponse, o as createRequestContext, s as getControllerContext } from "../pipeline-
|
|
6
|
-
import { t as defineAggregation } from "../defineAggregation-
|
|
7
|
-
import { a as mergeResourceConfig, i as defineResourceVariants, n as getEntityIdField, o as defineAction, r as getEntityQuery, t as getEntityId } from "../core-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-BxCoxmiN.mjs";
|
|
3
|
+
import { a as BulkMixin, c as collectReadBlockedFields, f as BodySanitizer, i as SlugMixin, l as isFieldReadable, m as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-CaQC5EXX.mjs";
|
|
4
|
+
import { a as ResourceDefinition, i as validateResourceConfig, n as assertValidConfig, o as createCrudRouter, r as formatValidationErrors, s as createPermissionMiddleware, t as defineResource } from "../defineResource-DR9vsUYy.mjs";
|
|
5
|
+
import { a as createFastifyHandler, c as getControllerScope, i as createCrudHandlers, l as sendControllerResponse, o as createRequestContext, s as getControllerContext } from "../pipeline-q69DZzgG.mjs";
|
|
6
|
+
import { t as defineAggregation } from "../defineAggregation-Nv-DwfOf.mjs";
|
|
7
|
+
import { a as mergeResourceConfig, i as defineResourceVariants, n as getEntityIdField, o as defineAction, r as getEntityQuery, t as getEntityId } from "../core-dxhcHhUD.mjs";
|
|
8
8
|
export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, sendControllerResponse, validateResourceConfig };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import "./constants-
|
|
3
|
-
import { t as defineResource } from "./defineResource-
|
|
1
|
+
/*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
|
|
2
|
+
import "./constants-BxCoxmiN.mjs";
|
|
3
|
+
import { t as defineResource } from "./defineResource-DR9vsUYy.mjs";
|
|
4
4
|
//#region src/core/defineAction.ts
|
|
5
5
|
/**
|
|
6
6
|
* Build an `ActionDefinition` with a typed handler. The literal schema
|